C言語でのWSTP開発(Mac OS X)

このドキュメントでは,Mac OS Xシステム上で,C言語で書かれたWolfram Symbolic Transfer Protocol (WSTP)プログラムをコンパイルし実行する方法を説明する.(「WSTPと外部プログラム通信」はWolfram言語とC言語の両方でWSTPプログラムを書く方法を記述したものである.)
このドキュメントは,コンパイラや他の開発ツールの使い方を教えたり,C言語でのプログラミング方法を教えたりするものではない.WSTPプログラムの構築や実行で問題がある場合は,このドキュメントの「トラブルシューティング」をご覧いただきたい.
このドキュメントで記述されていることの多くは,Unix独特のものであり,サポートされるすべてのUnixプラットフォームに適用できる.しかしMac OS Xマシンに特有の情報もある.別のプラットフォームでWSTPプログラムをコンパイルし実行する方法については,そのプラットフォームの開発者ガイドをご参照いただきたい.
サポートされる開発プラットフォーム
Mac OS X用のWSTP Developer Kit (WSDK)の中のwstp.framework共有ライブラリは,Mac OS X 10.9.0以降およびXcode 6.x以降で使うことができる.このフレームワークには32ビットのx86および64ビットのx86アーキテクチャに対するユニバーサルバイナリサポートが含まれる.
WSTPコンポーネントのインストール
WSTP Developer KitはWolframシステムディレクトリ内の$InstallationDirectory/SystemFiles/Links/WSTP/DeveloperKit/MacOSX-x86-64ディレクトリにある.

推奨されるインストール

CompilerAdditionsのインストール

WSTPプログラムを構築するのに必要なWSTPコンポーネントは,Wolframシステムバンドルですでにインストールされている.これらのコンポーネントを使う方法の一つとして,これらをMathematica.appディレクトリに残したままにしておき,コンパイラを呼び出すときにそのコンポーネントの完全パス名を指定するというものがある.「WSTPプログラムの構築」セクションの例題「makefiles」ではこのアプローチを使う.
別の方法として,コンパイラがこれらのコンポーネント(wstp.h,libWSTPi4.a,wstp.framework)を自動的に検索するディレクトリにコンポーネントをコピーするというものがある.このディレクトリは通常wstp.hでは/usr/includeか/usr/lib,wstp.frameworkでは/Library/Frameworksか~/Library/Frameworksである.多くのシステムで,すべてのユーザにこれらのディレクトリへの書込み許可があるとは限らない.

WSTPExamplesのインストール

WSTPExamplesディレクトリをホームディレクトリにコピーする.

WSTPフレームワークコンポーネント

以下はWSDKに含まれるそれぞれのファイルおよびディレクトリの説明である.

CompilerAdditionsディレクトリ

wstp.h
wstp.hはCあるいはC++のソースファイルに含まれなければならないヘッダファイルであり,コンパイラによって見付けられる場所になければならない.このヘッダファイルは,ソースファイルと同じディレクトリにコピーすることも,標準ヘッダファイルと同じ場所にコピーすることもできる.また,ヘッダファイルの検索パスにWSTPディレクトリを加えた場合はそのままの場所に置いておくこともできる.
libWSTPi4.a
libWSTPi4.aはWSTP関数すべてを含む静的ライブラリである.これは必ずプロジェクトに含まれていなければならない.このライブラリは,ソースファイルと同じディレクトリにコピーすることができる.ライブラリの検索パスにWSTPディレクトリを加えた場合は,そのままの場所に置いておくこともできる.
wstp.framework
wstp.frameworkはWSTP関数すべてを含む動的ライブラリのフレームワークである.WSTPライブラリと動的に接続するバージョンのプログラムが構築したい場合にこのフレームワークを使う.このライブラリはソースファイルを同じディレクトリにコピーすることができる.フレームワークの検索パスにWSTPディレクトリを加えた場合は,そのままの場所に置いておくこともできる.
wsprep
wsprepはテンプレートファイルを処理することにより自動的にWSTPプログラムを書くアプリケーションである.このアプリケーションは,プロジェクトと同じディレクトリにコピーするか,それへのエイリアスを作っておくと便利である.
wscc
wsccはWSTPソースファイルを前処理しコンパイルするスクリプトである.

WSTPExamplesディレクトリ

このディレクトリには非常に簡単ないくつかのWSTPプログラムのソースコードが含まれている.このソースコードを使うことによって,自分でコードを書かずにWSTPプログラムを構築して実行する方法が学べる.

PrebuiltExamplesディレクトリ

このディレクトリにはすでに構築された例題プログラムが含まれている.「WSTPプログラムの実行」ではそのプログラムのうちの2つを実行する方法を説明する.「WSTPプログラムの構築」ではWSTPExamplesディレクトリのソースコードを使って自分でプログラムを構築する方法を説明する.
WSTPプログラムの構築
WSTPプログラムを構築する一般的な手順は,WSTP関数を呼び出すCあるいはC++のソースファイルにwstp.hを加え,ソースファイルをコンパイルし,結果のオブジェクトコードをlibWSTPi4.aライブラリかwstp.framework,およびアプリケーションによって必要とされる他の標準ライブラリに連結するというものである.アプリケーションがWSTPテンプレートメカニズムを使っている場合,テンプレートファイルはまずwsprepを使ってCのソースファイルに処理されなければならない.

WSTPのテンプレートファイルを使う

「WSTPと外部プログラム通信」で説明してあるようにプログラムでWSTPテンプレートメカニズムを使う場合は,wsprepアプリケーションを使ってテンプレートエントリを含むソースファイルを同時に前処理しなければならない.テンプレートエントリは,テンプレートキーワードを含む行の列である.各エントリは,評価されたときに,関連付けられたC関数を呼び出すWolfram言語関数を定義する.wsprepがそのようなソースファイルを処理するとき,他のテキストを変更せずにテンプレートエントリをC関数に変換し,WSTPを使ってリモート手続き呼び出しメカニズムを実装する追加のC関数を書き出す.結果はコンパイルの準備ができたCのソースファイルである.
例えば,以下のコマンド
wsprep addtwo.tm -o addtwotm.c
は,addtwo.tmのテンプレートエントリと他のテキストからCのソースファイルaddtwotm.cを生成する.それからCコンパイラを使って出力ファイルをコンパイルする.プログラムの構築にmakeユーティリティを使っている場合は,makefileに以下の規則と類似の規則を加えることができる.
addtwotm.c  :  addtwo.tm
wsprep addtwo.tm -o addtwotm.c

コマンドラインからWSTPプログラムを構築する

次は,addtwofactorを含むWSDKのサンプルプログラムを構築するのに必要な,サンプルのmakefileである.サンプルプログラム(この場合はaddtwo)を構築するためにはWSTPExamplesディレクトリで以下のコマンドを評価する.

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'.

WSLINKDIR = /Applications/Mathematica.app/Contents/SystemFiles/Links/WSTP/DeveloperKit
SYS = MacOSX-x86-64
CADDSDIR = ${WSLINKDIR}/${SYS}/CompilerAdditions

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

WSPREP = ${CADDSDIR}/wsprep

EXTRA_LIBS = -lc++ -framework Foundation

WSTP_LIB = -lWSTPi4

all : addtwo bitops counter factor factor2 factor3 quotient reverse sumalist

addtwo : addtwotm.o addtwo.o
    ${CC} -I${INCDIR} addtwotm.o addtwo.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

bitops : bitopstm.o bitops.o
    ${CC} -I${INCDIR} bitopstm.o bitops.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

counter : countertm.o
    ${CC} -I${INCDIR} countertm.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

factor : factor.o
    ${CC} -I${INCDIR} factor.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

factor2 : factor2.o
    ${CC} -I${INCDIR} factor2.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

factor3 : factor3.o
    ${CC} -I${INCDIR} factor3.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

quotient : quotient.o
    ${CC} -I${INCDIR} quotient.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

reverse : reversetm.o
    ${CC} -I${INCDIR} reversetm.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -o $@

sumalist : sumalisttm.o sumalist.o
    ${CC} -I${INCDIR} sumalisttm.o sumalist.o -L${LIBDIR} ${WSTP_LIB} ${EXTRA_LIBS} -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プログラムを構築する場合,開発者はlibc++およびFoundationフレームワークと接続しなければならない.

XcodeでMac OS XのWSTPプログラムを構築する

Xcode 6.x+

addtwoのプロジェクトを作成する

addtwoを構築,編集,デバッグするために使うことのできるプロジェクトを作成する.

1.  Xcodeを起動する.

2.  FileメニューからNew Projectを選ぶ.

Choose a template for your new projectシートが現れる.

3.  OS XセクションでApplicationをクリックすしてCommand Line Toolアイコンをクリックする.Nextをクリックする.

Choose options for your new projectシートが現れる.

4.  Product Nameテキストボックスにaddtwoを入力する.TypeドロップメニューからCを選ぶ.Use Automatic Reference Countingチェックボックスのチェックを外す.Nextをクリックする.

Choose Folderシートが開く.

5.  ファイルシステムの中にaddtwoプロジェクトのためのディレクトリを作成する.addtwoプロジェクトをgitのレポジトリにする必要があるかどうかにより,Source Controlチェックボックスのチェックを付けるか外すかする.Createをクリックする.

Xcodeがaddtwoワークシートを開く.

6.  プロジェクトディレクトリにソースファイルをコピーする.

ターミナルアプリケーション(/Applications/Terminal.app)を起動し,Wolframシステムがインストールされているディレクトリに変更(cd)する.そのディレクトリに到達したら,cd$InstallationDirectory/SystemFiles/Links/WSTP/DeveloperKit/MacOSX-x86-64/WSTPExamplesを指定する.

コピーコマンド(cp)を使って,ステップ4で選んだプロジェクトディレクトリにaddtwoソースファイルをコピーする.

7.  テンプレートファイル上でwsprepを実行する.

ディレクトリをプロジェクトディレクトリに変更する.

wsprepを使ってソースファイルを生成する.

8.  プロジェクトにファイルを加える.

9.  プロジェクトからmain.cを削除する.

ファイルmain.cを右クリックしDeleteを選ぶ.ドロップダウンメニューでMove to Trashボタンをクリックする.

10.  プロジェクトを構築する.

ProjectメニューからBuildを選ぶ.

Factorのプロジェクトを作成する

factorを構築,編集,デバッグするために使うことのできるプロジェクトを作成する.

1.  Xcodeを起動する.

2.  FileメニューからNew Projectを選ぶ.

Choose a template for your new projectシートが現れる.

3.  OS XセクションでApplicationをクリックしてCommand Line Toolアイコンをクリックする.Nextをクリックする.

Choose options for your new projectシートが現れる.

4.  Product Nameテキストボックスに"factor"を入力する.TypeドロップメニューからCを選ぶ.Use Automatic Reference Countingチェックボックスのチェックを外す.Nextをクリックする.

Choose Folderシートが開く.

5.  ファイルシステムの中にfactorプロジェクトのためのディレクトリを作成する.addtwoプロジェクトをgitのレポジトリにする必要があるかどうかにより,Source Controlチェックボックスのチェックを付けるか外すかする.Createをクリックする.

Xcodeがaddtwoワークシートを開く.

6.  プロジェクトディレクトリにソースファイルをコピーする.

ターミナルアプリケーション(/Applications/Terminal.app)を起動し,Wolframシステムがインストールされているディレクトリに変更(cd)する.そのディレクトリに到達したら,cd$InstallationDirectory/SystemFiles/Links/WSTP/DeveloperKit/MacOSX-x86-64/WSTPExamplesを指定する.

コピーコマンド(cp)を使って,ステップ4で選んだプロジェクトディレクトリにfactorソースファイルをコピーする.

7.  プロジェクトにファイルを加える.

8.  プロジェクトからmain.cを削除する.

ファイルmain.cを右クリックしDeleteを選ぶ.ドロップダウンメニューでMove to Trashボタンをクリックする.

9.  プロジェクトを構築する.

ProjectメニューからBuildを選ぶ.

wsccを使う

wsccはWSTPソースファイルを前処理してコンパイルするスクリプトである.これはファイル名が.tmで終わるファイルすべてのWSTPテンプレートを前処理して,その結果のCソースコードに対してccを呼ぶ.wsccはコマンドラインオプションと他のファイルを直接ccに渡す.次がwsccを使ってaddtwoアプリケーションを構築するコマンドである.
wscc addtwo.tm addtwo.c -o addtwo
WSTPプログラムの実行
「WSTPプログラムの構築」の手順は,WSTPExamplesディレクトリのソースコードを使って2つのWSTPプログラムを構築する方法を説明するものである.これらの2つのプログラムaddtwofactorはすでにPrebuiltExamplesフォルダの中に構築されている.自分で構築する前にすでに構築された例題を実行してみて,WSTPシステム追加分がインストールされ正常に動いていることを確認し,プログラムが適切に構築されるとどのようなことが起こるかをこれらの例題から学んでおくとよい.ここでのコメントはすべてDeveloper Kitにあるプログラムを使っているものと想定したものである.

Wolfram言語カーネルからすでに構築された例題を実行する

最初の例題プログラム,addtwoはWolfram言語にインストールされているWSTPテンプレートプログラムである.つまり,このプログラムは背景で実行し,Wolfram言語のサービスとして,外部でコンパイルされた1つあるいは複数の関数を提供する.Wolfram言語ユーザにとって,これらの関数は組込みのように見える.この新しい機能を取得するためには,Wolfram言語ユーザはInstall[]関数を実行しなければならない.addtwoプログラムは,C関数のaddtwo()の呼出しとしてWolfram言語関数AddTwo[]を定義するテンプレートファイルを使う.テンプレートメカニズムについては「WSTPと外部プログラム通信」で説明してある.このプログラムのソースコードは以下のようなものである.
次の2つのセルを評価する:
新しく利用可能になった関数を見るためには,次のセルを評価する:
以下でファイルaddtwo.tmで定義されているAddTwo[]関数の使用法メッセージを表示する:
使ってみる:
2つの機械整数の和が機械整数に適合しない場合,あるいはどちらかの引数が機械整数でない場合にどうなるかを見てみる(2^31-1は最大の機械整数である.コンパイラが2バイト整数を使う場合は2^15-1が最大のC intである):
AddTwoプログラムは大きい整数には適していない:
以下はAddTwo[_Integer,_Integer]ではない:
Install[]LinkOpen[]を呼出し,外部プログラムを情報を交換してAddTwo[]の定義を設定する.この詳細について心配する必要はないが,興味がある方は以下を評価するとよい:
外部プログラムを使い終わったら,以下を評価する:

すでに構築された例題内からWolfram言語カーネルを起動する

2つ目の例題プログラムのfactorは,Wolfram言語カーネルが背景で動いており,factorのサービスとしてカーネルの計算サービス(この場合はユーザによって入力された整数を因数分解する機能)を提供するという意味で,Wolframシステムのフロントエンドであると言える.これらの例題は,Wolframシステムがアプリケーションディレクトリにインストールされているものと想定している.
以下のコマンドを実行して"factor"アプリケーションを起動する.
しばらくするとプロンプトが現れ,整数を入力するよう求める.10桁未満の整数をタイプしReturnを押す(他のfactor例題はタイプする整数の大きさの制約が緩い).
Wolfram言語により返された素因数が出力され,factorはWolfram言語とのリンクを閉じる.

サポートされるリンクプロトコル

C関数のWSOpenArgcArgv(),およびWolfram言語関数のLinkOpen[]については,「WSTPと外部プログラム通信」で説明してある.Mac OS XプラットフォームではLinkProtocolオプションの適正な値はTCPIPTCPSharedMemoryPipesIntraProcessである.LinkProtocolは接続の一端から他方へとデータを転送するのに使われるメカニズムである.LinkMode->LaunchリンクのデフォルトのプロトコルはSharedMemoryである.SharedMemoryLinkMode->ListenリンクおよびLinkMode->Connectリンクのデフォルトでもある.
TCPIPプロトコルとTCPプロトコルでは,リンク名は符号のない16ビットの整数である. "TCPIP"のリンク名が整数であっても,WLOpenArgcArgv()およびLinkOpen[]への桁の列として与えられる.
トラブルシューティング