用 C 語言開發 WSTP (Linux)

支持的開發平臺 運行 WSTP 程序
安裝 WSTP 組件 疑難解答
構建 WSTP 程序  

本文敘述了在 Linux 系統中如何編譯和運行用 C 語言編寫的 Wolfram Symbolic Transfer Protocol (WSTP) 程序. (「WSTP 和外部程序的通信」敘述瞭如何用 Wolfram 語言和 C 語言編寫 WSTP 程序.)html

本文並不教你如何使用編譯器和其它開發工具,也不會教你如何用 C 語言編程. 若是你有任何開發或運行 WSTP 程序的問題,請參閱本文末尾的「疑難解答」章節.前端

本文所敘述的大部份內容是專門面向 Linux 並適用於全部被支持的 Linux 平臺. 若想學習如何在其它平臺上編譯和運行用 WSTP 程序,請參閱相關平臺的開發指南.c++

支持的開發平臺

做爲一個共享庫,WSTP 能夠用於任何符合標準調用約定和由下列編譯器指定的二進制接口的開發環境.編程

當下面的某些編譯器與由編譯器建立產生的集成開發環境相集成時,它們的功能等價於 make 實用程序.數組

 

  C compiler C++ compiler
  "Linux" gcc (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3) g++ (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3)
  "Linux-x86-64" gcc (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3) g++ (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3)

除了上面所說的,編譯 WSTP API 還須要 libuuid 開發庫,在 Debian 系統內稱爲 uuid-dev,在 Red Hat 和 Suse 中則稱爲 libuuid-devel.app

安裝 WSTP 組件

WSTP 開發工具包(WSDK)位於 Wolfram 系統目錄內的$InstallationDirectory/SystemFiles/Links/WSTP/DeveloperKit/$SystemID 目錄中.框架

建議安裝

CompilerAdditions 安裝

構建 WSTP 程序所須要的 WSTP 組件已由 Wolfram 系統安裝器安裝. 使用這些組件的一種方法是讓它們保留在 Wolfram 系統目錄中,當調用編譯器時指定它們的完整路徑. 該方法列在「構建 WSTP 程序」章節中的範例「makefiles」中.ide

另外一種方法是把這些組件 (wstp.h、libWSTP32i4.a、libWSTP32i4.so、libWSTP64i4.a 和 libWSTP64i4.so) 複製到編譯器會自動搜索這些文件的目錄中. 這些目錄通常是 /usr/include 和 /usr/lib,可是你的系統可能會有所不一樣. 在許多系統中,不是全部用戶均可以讀寫這些目錄.函數

WSTPExamples 安裝

把 WSTPExamples 目錄複製到主目錄.工具

WSTP 框架組件

下面是 WSDK 中每一個文件或目錄的說明.

CompilerAdditions 目錄

wstp.h

wstp.h 是一個必須包含在 C 和 C++ 源文件中的頭文件. 它應該放在你的編譯器能夠找到的地方. 你能夠把它複製到和源文件一樣的目錄下,或複製到和標準頭文件一樣的目錄下,或者不用管它,可是把 WSTP 目錄添加到頭文件的搜索路徑中.

libWSTP32i4.a/libWSTP64i4.a

這是一個包含全部 WSTP 函數的靜態庫. 你的項目應該包含它. 你能夠把該庫複製到與源文件一樣的目錄下或不作任何改變,可是把 WSTP 目錄添加到庫文件的搜索路徑中. 32/64 代表庫是 WSTP 庫的 32 位或 64 位版本.

libWSTP32i4.so/libWSTP64i4.so

這是一個包含 WSTP 全部函數的動態共享庫. 你的項目應該包含它. 你能夠把該庫複製到與源文件一樣的目錄下,或複製到系統位置,例如 /lib 或 /usr/lib,或不作任何改變,可是把 WSTP 目錄添加到庫搜索路徑中. 32/64 代表庫是 WSTP 庫的 32 位或 64 位版本.

wsprep

wsprep 是一個應用程序,經過處理模板文件自動編寫 WSTP 程序. 把該應用程序複製到你的項目目錄中或建立一個別名會方便應用.

wscc

wscc 是一個預處理和編譯 WSTP 源文件的腳本.

WSTPExamples 目錄

該目錄包含一些很是簡單的 WSTP 程序源代碼. 經過使用源代碼,你能夠學習如何構建和運行 WSTP 程序,而無需本身編寫任何代碼.

PrebuiltExamples 文件夾

該目錄包含範例程序的預建版本. 「運行 WSTP 程序」描述瞭如何運行兩個這樣的程序. 「構建 WSTP 程序」描述瞭如何使用 WSTPExamples 文件夾中的源代碼構建本身的程序.

構建 WSTP 程序

構建 WSTP 程序的通常過程是在任何調用 WSTP 函數的 C 或 C++ 源文件中包含 wstp.h,編譯源文件,而後把 libWSTP32i4.a、libWSTP64i4.a、libWSTP32i4.so 或 libWSTP64i4.so 與結果對象代碼相連接. 若是你的應用程序使用 WSTP 模板機制,那麼你的模板文件必須首先使用 wsprep 處理成 C 源文件.

使用 WSTP 模板文件

若是你的程序使用「WSTP 和外部程序通信」中描述的 WSTP 模板機制,你必須同時使用 wsprep 應用程序預處理包含模板項的源文件.(模板項是包含模板關鍵字的行序列,每一項定義當調用相關 C 函數時的 Wolfram 語言函數.)當 wsprep 處理這類文件時,它會把模板項轉換成 C 函數,傳遞未改變的文本,並使用 WSTP 應用遠程過程調用機制編寫其餘 C 函數. 結果是可用於編譯的 C 源文件.

例如,命令

wsprep addtwo.tm -o addtwotm.c

 

會從模板項中產生一個 C 源文件 addtwotm.c,其餘文本保留在 addtwo.tm. 而後你可使用 C 編譯器編譯輸出文件. 若是你使用 make 工具構建你的程序,你能夠添加相似下面的規則至你的 makefile.

addtwotm.c : addtwo.tm
wsprep addtwo.tm -o addtwotm.c

 

構建 WSTP 程序

如下是一個構建 WSDK 中樣本程序須要的樣本 makefile,包括 addtwo 和 factor. 要構建樣本程序,例如 addtwo,在 WSTPExamples 目錄中計算如下命令.

make addtwo

 

使用 Makefile

# This makefile can be used to build all or some of the sample
# programs. To build all of them, use the command
# 'make all'. To build one, say addtwo, use the command
# 'make addtwo'.

WSTPLINKDIR = /usr/local/Wolfram/Mathematica/10.0/SystemFiles/Links/WSTP/DeveloperKit
SYS = Linux # Set this value with the result of evaluating $SystemID
CADDSDIR = ${WSTPLINKDIR}/${SYS}/CompilerAdditions

INCDIR = ${CADDSDIR}
LIBDIR = ${CADDSDIR}

EXTRALIBS = -lm -lpthread -lrt -lstdc++ -ldl -libuuid # Set these with appropriate libs for your system.
WSTPLIB = WSTP32i4 # Set this to WSTP64i4 if using a 64-bit system

WSPREP = ${CADDSDIR}/wsprep

all : addtwo bitops counter factor factor2 factor3 quotient reverse sumalist

addtwo : addtwotm.o addtwo.o
    ${CC} -I${INCDIR} addtwotm.o addtwo.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@

bitops : bitopstm.o bitops.o
    ${CC} -I${INCDIR} bitopstm.o bitops.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@

counter : countertm.o
    ${CC} -I${INCDIR} countertm.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@

factor : factor.o
    ${CC} -I${INCDIR} factor.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@

factor2 : factor2.o
    ${CC} -I${INCDIR} factor2.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@

factor3 : factor3.o
    ${CC} -I${INCDIR} factor3.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@

quotient : quotient.o
    ${CC} -I${INCDIR} quotient.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@

reverse : reversetm.o
    ${CC} -I${INCDIR} reversetm.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@

sumalist : sumalisttm.o sumalist.o
    ${CC} -I${INCDIR} sumalisttm.o sumalist.o -L${LIBDIR} -l${WSTPLIB} ${EXTRALIBS} -o $@

.c.o :
    ${CC} -c -I${INCDIR} $<

addtwotm.c : addtwo.tm
    ${WSPREP} $? -o $@

bitopstm.c : bitops.tm
    ${WSPREP} $? -o $@

countertm.c : counter.tm
    ${WSPREP} $? -o $@

reversetm.c : reverse.tm
    ${WSPREP} $? -o $@

sumalisttm.c : sumalist.tm
    ${WSPREP} $? -o $@

 

使用下表肯定在你的系統中連接 WSTP 程序時是否須要其餘庫.

 

  $SystemID EXTRALIBS
  "Linux" -lm -lpthread -lrt -lstdc++ -ldl -luuid
  "Linux-x86-64" -lm -lpthread -lrt -lstdc++ -ldl -luuid

使用 wscc

wscc 是一個預處理和編譯 WSTP 源文件的腳本. 它會預處理任何以 .tm 結尾的文件中的 WSTP 模板,而後在結果 C 源代碼中調用 cc. wscc 會直接傳遞命令行選項和其餘文件至 cc. 如下是使用 wscc 構建 addtwo 應用的命令.

wscc addtwo.tm addtwo.c -o addtwo

運行 WSTP 程序

構建 WSTP 程序」中的說明描述瞭如何使用 WSTPExamples 目錄中的源代碼構建兩個 WSTP 程序. 這兩個程序,addtwo 和 factor 已存在於 PrebuiltExamples 文件夾. 在構建你本身的以前,應該試着運行預建的範例以驗證 WSTP 系統附件是否安裝且正常工做,並學習當正確構建時這些範例會有怎樣的結果.

有兩個 WSTP 的基本類型程序,addtwo 和 factor 程序. 第一個是可安裝程序. 一個可安裝程序經過調用機制連接 C 程序和內核,爲內核提供新的功能. 爲了得到此新功能,Wolfram 語言必須運行 Install[] 函數. 在 addtwo 範例中,你會添加一個新的函數,稱做 AddTwo[],相加兩個數(以參數形式提供). 內核與可安裝程序具備特殊的關係,容許它們可互相交流. 當運行可安裝程序時,爲了鏈接,它會須要你提供一些信息. 程序的另外一個類型是前端. 前端進行全部建立和管理自身連接的工做. 除了 factor 範例以外,Wolfram 系統前端和 Wolfram 語言內核也是前端類型中的一個例子. 前端運行不須要任何其餘信息,可是在執行的某點會進行鏈接.

在 Wolfram 語言內核中運行預建範例

第一個範例程序,addtwo 是安裝在 Wolfram 語言中的一個 WSTP 模板程序. 也就是說,該程序在後臺運行,爲 Wolfram 語言,一個或多個外部編譯函數提供服務. 對於 Wolfram 語言用戶,這些函數顯現爲內置的. addtwo 程序使用定義 Wolfram 語言函數的模板文件 AddTwo[] 做爲一個對 C 函數 addtwo()的調用. (模板機制的詳細描述參見「WSTP 和外部程序通信」.)該程序的源代碼爲:

:Begin:
:Function: addtwo
:Pattern: AddTwo[i_Integer, j_Integer]
:Arguments: { i, j }
:ArgumentTypes: { Integer, Integer }
:ReturnType: Integer
:End:

:Evaluate: AddTwo::usage = "AddTwo[x, y] gives the sum of two machine integers x and y."

int addtwo( int i, int j)
{
    return i+j;
}

int main(int argc; char* argv[])
{
    return WSMain(argc, argv);
}

 

編輯路徑字符串並計算下面兩個單元.

 

Click for copyable input

 

Click for copyable input

查找最新可用函數的列表,計算下面單元.

 

Click for copyable input

如下會顯示定義在文件 addtwo.tm 中的 AddTwo[] 函數的用法信息.

 

Click for copyable input

嘗試一下.

 

Click for copyable input

看看若是兩個機器整數的和不匹配於一個機器的整數或若是任何一個參數都不是機器整數,會出現什麼狀況. (2^31-1 是最大的機器整數. 若是您的編譯器使用2個字節整數,那麼 2^15-1 是最大的 C int.)

 

Click for copyable input

addtwo 程序不適於大的整數.

 

Click for copyable input

如下不匹配 AddTwo[_Integer,_Integer].

 

Click for copyable input

Install[] 調用 LinkOpen[],而後和外部程序交換信息,設置 AddTwo[] 的定義. 你無需考慮這些細節,可是若是你很好奇,可執行如下命令.

 

Click for copyable input

當你再也不使用外部程序,執行以下命令.

 

Click for copyable input

從一個預建的範例中調用 Wolfram 語言內核

第二個範例程序,factor 是運行在後臺的 Wolfram 語言內核爲 factor 提供服務,內核的計算服務,Wolfram 系統的前端對用戶的輸入整數給出因式分解.

經過執行如下命令,啓動 factor 應用.

factor -linkmode launch -linkname 'math -mathlink'

 

過一會會出現提示要求你輸入整數. 敲入少於 10 位的整數,而後按下 Enter 鍵.(其餘 factor 例子會放寬對輸入整數大小的限制.)

Integer to factor:

 

輸出由 Wolfram 語言產生的質因數分解,而後 factor 關閉它與 Wolfram 語言的連接.

Integer to factor: 123456789
3 ^ 2
3607 ^ 1
3803 ^ 1

 

支持的連接協議

C 函數 WSOpenArgcArgv() 和 Wolfram 語言函數 LinkOpen[] 的細節請參見「WSTP 和外部程序通信」. 在 Linux 機器中,LinkProtocol 選項的合法值爲 "TCPIP"、"TCP"、"SharedMemory"、"Pipes" 和 "IntraProcess". LinkProtocol 是用於從一端到另外一端傳輸數據的機制. "SharedMemory" 是 LinkMode->Launch 連接的默認協議. 全部 LinkMode->Listen 和 LinkMode->Connect 連接的默認值是 "SharedMemory".

請注意,"TCPIP" 和 "TCP" 協議的連接名稱是 16 位無符號整數. 雖然 "TCPIP" 連接的名稱是整數,可是它們仍然以(數字)字符串形式賦給 WSOpenArgcArgv() 和 LinkOpen[].

疑難解答

  • 一旦你的程序正常工做,就可關閉編譯器優化功能. 這可以使編譯速度更快,更容易調試,另外,優化可能被打斷,會致使一些問題.(優化代碼使用的堆棧和寄存器的方式不一樣於非優化的代碼,可能暴露或掩蓋代碼中的錯誤. 例如,返回一個局部變量指針時出現的常見錯誤可能會或不會致使問題,其取決於堆棧和寄存器使用.)
  • 檢查從 WSTP 庫函數的返回值或在你的程序關鍵部分調用 WSError(). WSTP 每每能夠告訴你什麼地方出了錯.
  • 文件 wstp.h、libWSTP32i4.a 和 libWSTP32i4.so(64位平臺爲 libWSTP64i4.*)是配套的集合. 若是你在使用早期的 WSTP 版本,當創建你的應用程序時,應該注意不要混淆它們.
  • 檢查你使用的 C 編譯器是否支持雛形,若是不支持,你須要改變代碼或構建項目的方式. 詳細解釋請參見「構建 WSTP 程序」.
  • 檢查以確保你的程序與 libstdc++ 和基礎框架相連接. 沒有這些依賴,構建二進制時會在連接狀態時失敗.

相關指南

相關教程

相關文章
相關標籤/搜索