$DLLLOAD(DLLロード関数)
ユーザ関数を実装したDLLをロードし、オブジェクトを取得します。
ロードに成功すると、取得したDLLオブジェクトを返します。ロードに失敗した場合、0バイトの文字列を返します。
- 〈このページの構成〉
形式
DLLオブジェクト=$DLLLOAD(DLL名)
指定する値
-
DLLオブジェクト
DLLオブジェクトを設定する変数名を指定します。
-
DLL名
ロードするDLLの名称を定数または変数で指定します。定数を指定する場合は、「'(シングルクォーテーション)」で囲みます。
DLLの名称は、jamscriptコマンドの-bpオプションで指定したベースパスを基点にした相対パスで指定します。-bpオプションを省略した場合は、Asset Consoleのインストール先フォルダ\scriptworkが基点となります。
使用するDLLのインターフェース
呼び出されるDLLに、次の3つの実行制御関数をエクスポートしておく必要があります。
-
インスタンス初期化のためのaim_init関数
-
エラーメッセージ応答のためのaim_getmessage関数
-
インスタンス解放のためのaim_free関数
各実行制御関数の形式を次に示します。
void* aim_init() void aim_free(void* dllobj) int aim_getmessage(void* dllobj, char** msg)
DLLのロード成功時は、インスタンス生成のためにaim_init関数を呼び出します。aim_init関数のリターンには、エラーがありません。エラー発生時に、詳細なエラー情報をログファイルに出力するには、エラーメッセージのアドレスなどをaim_init関数のリターン情報としてください。また、エラーメッセージをAsset Consoleのログファイルに出力するには、aim_init関数のあとに呼び出されるaim_getmessage関数でメッセージを設定してください。
スクリプト側では、エラーを組み込み関数$GETSTATUSで検出したら、組み込み関数$DLLFREEを実行し、DLLを解放してください。$DLLFREEの実行によってaim_free関数が呼び出されるので、aim_init関数のリターン情報の情報域を開放してください。
なお、aim_init関数が正常終了した場合には、必ずaim_getmessage関数は0をリターンしてください。これで組み込み関数$DLLEXEC2が実行可能な状態となります。
終了状態
処理の終了状態とその内容を次に示します。
終了状態 |
内容 |
---|---|
NORMAL |
正常終了 |
NODATA |
− |
ERROR |
次のどれかを示す
|
スクリプト中断 |
次のどれかを示す
|
- (凡例)
-
−:該当しない
注意事項
組み込み関数$DLLLOADでロードするDLLは、あらかじめ用意しておく必要があります。コンパイル時には、Asset Consoleが提供しているヘッダーファイルをソースファイルと一緒にコンパイル環境に格納して、コンパイルしてください。また、コンパイルする際は、オプションに「/MT」を指定してください。
ヘッダーファイルの格納先を次に示します。
Asset Consoleのインストール先フォルダ\sdk\include
記述例
$DLLEXEC2(DLL実行関数)の記述例を参照してください。
実行制御関数の作成
Asset ConsoleのスクリプトからDLLのユーザ関数を呼び出すためには、次の3つの実行制御関数が必要です。
-
aim_init
-
aim_free
-
aim_getmessage
■aim_init
- 機能
-
インスタンスを作成し、戻り値にそのアドレスを設定します。これによって、それ以降ほかの関数では、aim_init関数で作成したアドレスを取得できます。インスタンス内に値を保持することで、スレッド間の競合を避けられます。
- 形式
void* aim_init()
- 戻り値
-
-
関数が成功した場合、このDLLで使用するハンドルのアドレスを返します。アドレスはNULLでもかまいません。リターン直後、aim_getmessage関数が呼ばれるので、必ず0をリターンしてください。
-
継続可能なエラーや、エラーの内容をAsset Consoleのログファイルに出力する場合、エラー情報を設定したハンドルのアドレスを返して、aim_getmessage関数でメッセージを取得できるようにします。また、同時にスクリプトの終了状態を決定するリターンコードを返すようにします。リターンコードについては、aim_getmessage関数の戻り値を参照してください。
-
■aim_free
- 機能
-
aim_init関数で作成したインスタンスを解放します。
- 形式
void aim_free(void* dllobj)
- 引数
-
-
dllobj(入力情報)
aim_init関数で作成したインスタンス
-
■aim_getmessage
- 機能
-
作成するDLL内のメッセージを、Asset Consoleのログに出力したり、スクリプトで容易に取得したりできます。aim_getmessage関数は、次に示すタイミングで呼び出されます。
-
aim_init関数の実行後
msgの内容をAsset Consoleのログに出力します。
-
作成した関数の実行後
関数の戻り値が負数(スクリプト中断エラー発生時)の場合に実行し、必要に応じてmsgにアドレスを設定します。メッセージを設定した場合は、msgの内容がAsset Consoleのログに出力されます。
-
組み込み関数$DLLMSG実行時
組み込み関数$DLLMSGで実行され、メッセージを変数で取得します。
-
- 形式
int aim_getmessage(void* dllobj, char** msg)
- 引数
-
-
dllobj(入力情報)
aim_init関数で作成したインスタンス
-
msg(出力情報)
メッセージが格納されたアドレス
-
- 戻り値
-
戻り値と内容、および戻り値に応じて実行される処理を次に示します。
戻り値
内容
実行できる処理
0
正常終了
スクリプトの状態をNORMALに変更
1
Warning
スクリプトの状態をNODATAに変更
正数
Error
スクリプトの状態をERRORに変更
負数
強制終了
スクリプトを強制終了
- コーディング例
-
DLLのソースファイルのコーディング例を示したあと、アクセス定義ファイルからの呼び出しと関連づけについて説明します。
-
DLLのソースファイル(C++)
#include <stdio.h> #include <windows.h> #include "jamScriptAPI.h" extern "C" __declspec(dllexport) void* aim_init(); extern "C" __declspec(dllexport) void aim_free(void*); extern "C" __declspec(dllexport) int aim_getmessage(void*, char**); extern "C" __declspec(dllexport) int DllFunc1(int, void**); extern "C" __declspec(dllexport) int DllFunc2(int, void**); typedef struct aimsample{ int status; int datalen; char** data; char message[256]; }AIMSAMPLE; BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { return TRUE; } void* aim_init() { AIMSAMPLE* dllobj = NULL; dllobj = (AIMSAMPLE*)LocalAlloc(LMEM_FIXED, sizeof(AIMSAMPLE)); if(!dllobj) { /* エラー処理 */ return NULL; } dllobj->status = 0; dllobj->datalen = 0; dllobj->data = NULL; *(dllobj->message) = '\0'; return dllobj; } void aim_free(void* dllobj) { int i; if(dllobj){ if(dllobj->data){ for(i=0;i<dllobj->datalen;i++){ if(*(dllobj->data+i)){ LocalFree(*(dllobj->data+i)); *(dllobj->data+i) = NULL; } } LocalFree(dllobj->data); dllobj->data = NULL; } LocalFree(dllobj); } } int aim_getmessage(void* dllobj, char** message) { if(dllobj){ *message = ((AIMSAMPLE*)dllobj)->message; } return 0; } int DllFunc1(int argc, void** argv) { AIMSAMPLE* dllobj = NULL; int i,status,length; char* data; if(argc != 1){ /* エラー処理 */ return -1; } /*aim_initで返却したエリアを取得*/ dllobj = (AIMSAMPLE*)$GETINITAREA(argv); if(!dllobj){ /* エラー処理 */ strcpy(dllobj->message, "引数の指定に誤りがあります。"); return -1; } if(dllobj->status != 0){ strcpy(dllobj->message, "呼び出し順序に誤りがあります。"); return -1; } length = $GETARRAYLENGTH(argv, argv[0]); status = $GETSTATUS(argv); if(status != JAM_SCRIPTAPI_NORMAL){ /* エラー処理 */ strcpy(dllobj->message, "$GETARRAYLENGTH関数でエラーを検知しました。"); return -1; } dllobj->datalen = length; dllobj->data = (char**)LocalAlloc(LMEM_FIXED, sizeof(char*)*length); if(!dllobj->data){ /* エラー処理 */ strcpy(dllobj->message, "メモリ確保に失敗しました。"); return -1; } ZeroMemory(dllobj->data, sizeof(char*)*length); for(i=0;i<length;i++){ data = (char*)$GETARRAY(argv, argv[0], i+1); status = $GETSTATUS(argv); if(status != JAM_SCRIPTAPI_NORMAL){ /* エラー処理 */ strcpy(dllobj->message, "$GETARRAY関数でエラーを検知しました。"); return -1; } *(dllobj->data+length-(i+1)) = (char*)LocalAlloc(LMEM_FIXED, strlen(data)+1); if(!*(dllobj->data+length-(i+1))){ /* エラー処理 */ strcpy(dllobj->message, "メモリ確保に失敗しました。"); return -1; } strcpy(*(dllobj->data+length-(i+1)), data); } /* 固有の処理 */ dllobj->status = 1; *(dllobj->message) = '\0'; return 0; } int DllFunc2(int argc, void** argv) { AIMSAMPLE* dllobj = NULL; int i; if(argc != 1){ /* エラー処理 */ return -1; } /*aim_initで返却したエリアを取得*/ dllobj = (AIMSAMPLE*)$GETINITAREA(argv); if(!dllobj){ /* エラー処理 */ return -1; } if(dllobj->status != 1){ strcpy(dllobj->message, "呼び出し順序に誤りがあります。"); return -1; } if(dllobj->data){ for(i=0;i<dllobj->datalen;i++){ if(*(dllobj->data+i)){ $SETARRAY(argv, argv[0], *(dllobj->data+i)); } } } dllobj->status = 2; *(dllobj->message) = '\0'; return 0; }
-
アクセス定義ファイルからの呼び出しと関連づけ
この例では、「DllFunc1」で取得した配列データの逆順を「DllFunc2」で出力します。また、「DllFunc1」、「DllFunc2」の順序で実行されない場合には、スクリプトを中断します。
#AssetInformationManager HTML 0005 [VAR] DLLOBJ DATA STATUS[ARRAY] ARY1 ARY2 [SET_VALUE] DLLOBJ = $DLLLOAD('jamsample.dll') STATUS = $GETSTATUS() [IF] STATUS != NORMAL [THEN] [SET_VALUE] #エラー処理 $EXIT(1) [IF_END] [SET_VALUE] $SETARRAY(ARY1, 1) $SETARRAY(ARY1, 2) $SETARRAY(ARY1, 3) $DLLEXEC2(DLLOBJ,'DllFunc1',ARY1) $DLLEXEC2(DLLOBJ,'DllFunc2',ARY2) DATA = $GETARRAY(ARY2,1) $ECHO(DATA) DATA = $GETARRAY(ARY2,2) $ECHO(DATA) DATA = $GETARRAY(ARY2,3) $ECHO(DATA) $DLLFREE(DLLOBJ)
- 出力結果
-
3
2
1
-