Please note that the recommended version of Scilab is 2025.0.0. This page might be outdated.
See the recommended documentation of this function
API_Scilab入門
C, C++ またはfortranコードを新しい関数としてScilabエンジンに読み込む方法
説明
api_scilabプレゼンテーション で説明されたように, ScilabはC, C++またはFortranコード(ソースまたはライブラリ)で言語を 拡張するためのAPIを提供します.
Scilabエンジンとアプリケーションコードの間のリンクは
gateway
と呼ばれます.
多くの場合, 処理は常に同じで,以下のようになります:
ユーザに指定された(入力及び出力)引数の数を調べます.
例えば,関数
foo(x)
がfoo()
またはfoo(2,3)
のようにコールされ, ユーザが答を得ます.入力引数の管理
複数の処理を行います:
入力引数Xの変数アドレスを取得します
関数
SciErr getVarAddressFromPosition(void* context, int positionOfTheVariable, int** address)
変数の型を調べます: doubleの行列 (複素数または複素数以外), 文字列 , 等
SciErr getVarType(void* context, int* positionOfTheVariable, int* Type)
他の関数も提供されています:
int isBooleanType(void* context, int* address)
int isBooleanSparseType(void* context, int* address)
int isDoubleType(void* context, int* address)
int isIntegerType(void* context, int* address)
int isPointerType(void* context, int* address)
int isPolyType(void* context, int* address)
int isSparseType(void* context, int* address)
int isStringType(void* context, int* address)
int isListType(void* context, int* address)
int isTListType(void* context, int* address)
int isMListType(void* context, int* address)
関連する場合, 入力引数かどうかを確認します.
int isVarComplex(void* context, int* address)
整数を処理する場合,さらに整数の精度も確認します
SciErr getMatrixOfIntegerPrecision(void* context, int* address, int* precision)
変数の大きさを確認します: 正方行列, スカラー, 等
大きさに関する情報を取得する際にも 実際のデータを取得する際に使用するものと同じ関数を使用します. 例えば, double の行列の場合 関数コール
SciErr getMatrixOfDouble(void* context, int* address, int* nbRows, int* nbCols, double** theActualData)
により行列の次元を取得できます.ほぼ全てのScilabデータ型にはこのような処理を行うための 同様なC関数があります.
その他, 特定の値かどうかを調べたり, 最初と2番目の入力引数の間の整合性を 確認したりすること等も可能です.
データ変換 (オプション).
使用するコードまたはライブラリによっては, いくつかの変換をデータに適用することができます. 古典的な例は行列の記録を列形式から線形式に変換するものです.
通常,このようにすると性能が低下することに注意してください.
アプリケーションコード
確認とデータ取得を行った後,実際の主コードをコールできます. 実際の情報処理(処理, データ変換, 等)をここで実行します.
これは,
src/c
,src/cpp
またはsrc/fortran
に保存,構築した サードパーティのコードにより行いますが, ライブラリ形式とすることも可能です. あらゆるライブラリをScilabにリンクすることができます.Scilabエンジンの出力引数を作成する
通常,アプリケーションコードの実行後, 何らかのデータをScilabインタプリタから戻します.
例えば, doubleの行列をScilabエンジンに保存する場合,C関数
SciErr createMatrixOfDouble(void* context, int position, int nbRows, int nbCols, const double* matrixOfDouble)
をコールします.通常,位置は
nbInputArgument(pvApiCtx) + X
により取得できます.X
が返す出力引数の位置となります. 例えば, 関数プロファイル[a, b, c] = foo();
nbInputArgument(pvApiCtx) + 3
は 変数c
となります.作成できる次元はゲートウェイの制約を受けることに注意してください.
ほぼ全てのScilabデータ型はこのような処理を行う同様なC関数を有します.
Scilabエンジンに出力引数を返す
以下, タスク4で, 作成した変数を返します.
a
を返す 前の例[a, b, c] = foo();
の場合, 以下の宣言を行います:AssignOutputVariable(pvApiCtx, 1) = nbInputArgument(pvApiCtx) + 1;
Scilabエンジンに新しい変数をコミットするには, 関数 ReturnArguments(pvApiCtx) をコールします.
ほぼ全てのAPI_Scilab関数がエラーに関する多くの情報を含む SciErrと呼ばれるC構造体を返すことに注意してください.
デフォルトでは, Scilab数値はC言語のdouble
型に保存されます.
習慣的に,
ゲートウェイは,sci_gateway/c/
(または /cpp/
)
に保存され,sci_functionName.c
という名前が付けられます.
pvApiCtx
は,グローバルコンテキスト変数です.
これは,バージョン5系では使用されていませんが, Scilab バージョン 6で導入される
マルチスレッド機能を管理するために導入されています.
実用的な例
以下のScilab関数を例として示します:
[c,d] = foo(a,b)
a
はdouble行列,a
と同じ大きさの
b
は論理値行列,
foo はa
の各要素に2を乗じて,
c
として返します.
また,bを要素毎に逆の論理値に変換して返します.
Scilabバイナリに含まれるツールボックススケルトンでサンプルを取得できます.
パスは
contrib/toolbox_skeleton/sci_gateway/c/sci_foo.c
です.
詳細な説明は以下の例のCコメント形式で提供されています.
// 完全なソースはtoolboxスケルトンのsci_gateway/c/ ディレクトリにあります // 標準ヘッダ #include "api_scilab.h" #include "BOOL.h" // 関数宣言 int sci_foo(char *fname, unsigned long fname_len) { // エラー管理変数 SciErr sciErr; ////////// 変数宣言 ////////// int m1 = 0, n1 = 0; int *piAddressVarOne = NULL; double *matrixOfDouble = NULL; double *newMatrixOfDouble = NULL; int m2 = 0, n2 = 0; int *piAddressVarTwo = NULL; int *matrixOfBoolean = NULL; int *newMatrixOfBoolean = NULL; int i = 0; ////////// 入力/出力引数の数を調べる ////////// /* --> [c, d] = foo(a, b) */ /* 入力引数が2のみであることを調べる */ /* 出力引数が2のみであることを調べる */ CheckInputArgument(pvApiCtx, 2, 2) ; CheckOutputArgument(pvApiCtx, 2, 2) ; ////////// 最初の入力引数 (double) を管理 ////////// /* 入力アドレスを取得 */ sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddressVarOne); if (sciErr.iErr) { printError(&sciErr, 0); return 0; } /* 最初の入力引数が実数行列(複素数でない)であることを調べる */ if ( !isDoubleType(pvApiCtx, piAddressVarOne) || isVarComplex(pvApiCtx, piAddressVarOne) ) { Scierror(999, "%s: Wrong type for input argument #%d: A real matrix expected.\n", fname, 1); return 0; } /* 行列を取得 */ sciErr = getMatrixOfDouble(pvApiCtx, piAddressVarOne, &m1, &n1, &matrixOfDouble); if (sciErr.iErr) { printError(&sciErr, 0); return 0; } ////////// 2番目の入力引数を管理 (論理値) ////////// /* 入力アドレスを取得 */ sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddressVarTwo); if (sciErr.iErr) { printError(&sciErr, 0); return 0; } if ( !isBooleanType(pvApiCtx, piAddressVarTwo) ) { Scierror(999, "%s: Wrong type for input argument #%d: A boolean matrix expected.\n", fname, 2); return 0; } /* 行列を取得 */ sciErr = getMatrixOfBoolean(pvApiCtx, piAddressVarTwo, &m2, &n2, &matrixOfBoolean); if (sciErr.iErr) { printError(&sciErr, 0); return 0; } ////////// 2つの入力引数の相関を確認 ////////// if ((m1 != m2) || (n1 != n2)) { Scierror(999, "%s: Wrong size for input arguments: Same size expected.\n", fname, 1); return 0; } newMatrixOfDouble = (double*)malloc(sizeof(double) * m1 * n1); ////////// アプリケーションコード ////////// // ライブラリへのコールで置換することができます for (i = 0; i < m1 * n1; i++) { /* 行列の各要素を2倍します */ newMatrixOfDouble[i] = matrixOfDouble[i] * 2; } newMatrixOfBoolean = (int*)malloc(sizeof(BOOL) * m2 * n2); for (i = 0; i < m2 * n2; i++) { /* 行列の各要素について, 値を反転する */ newMatrixOfBoolean[i] = ((matrixOfBoolean[i] == TRUE) ? FALSE : TRUE); } ////////// 出力引数を作成 ////////// /* 関数の戻り値として行列を作成 */ sciErr = createMatrixOfDouble(pvApiCtx, nbInputArgument(pvApiCtx) + 1, m1, n1, newMatrixOfDouble); free(newMatrixOfDouble); // データをScilabメモリにコピー if (sciErr.iErr) { free(newMatrixOfBoolean); // エラーの際,完全にクリンナップします printError(&sciErr, 0); return 0; } /* 関数の戻り値として行列を作成 */ sciErr = createMatrixOfBoolean(pvApiCtx, nbInputArgument(pvApiCtx) + 2, m2, n2, newMatrixOfBoolean); free(newMatrixOfBoolean); // データをScilabメモリにコピー if (sciErr.iErr) { printError(&sciErr, 0); return 0; } ////////// 出力引数をScilabエンジンに戻す ////////// AssignOutputVariable(pvApiCtx, 1) = nbInputArgument(pvApiCtx) + 1; AssignOutputVariable(pvApiCtx, 2) = nbInputArgument(pvApiCtx) + 2; return 0; }
このコードを構築,Scilabにロードする際,Scilabの動的リンク機能を使用します. この組み込み処理はScilabに委任するため,以下のコードはマルチプラットフォーム対応です.
files=["sci_foo.c"]; // TODO: WTF ? WITHOUT_AUTO_PUTLHSVAR = %t; ilib_build('build_lib',['foo','sci_foo'],files,[]); exec loader.sce [c, d] = foo([2,%pi], [%t, %f])
種々の確認が行われます:
-->[c, d] = foo(2, 2) !--error 999 foo: Wrong type for input argument #2: A boolean matrix expected.
-->[c, d] = foo([2,%pi], [%t, %f]) d = F T c = 4. 6.2831853
Report an issue | ||
<< api_scilab | API Scilab | call_scilab API >> |