Written in Japanese(UTF-8)
2014.8.30
INASOFT


/トップ/いじくるつくーる/ダウンロード/WebHelp/ヘルプトップ/


DLLの呼び出しルール



 ここには R-Script のCallDll()関数などから呼び出されるDLLの記述ルールについて書かれています。
 ここではC/C++言語で作られることを前提にしています。
 具体的なサンプルについては、ソースコードを入手し、各DLLのソールファイルやヘッダファイルを参照して下さい。




1. DLLの一般的な記述方法や作成方法について


 WindowsのDLLファイルの一般的な記述方法や作成方法については、一般的なWindowsプログラミングの参考書籍を参照して下さい。


2. DllMain()


 DllMain() については、特に規定はありません。


3. 数値型を返却値とする関数の呼び出し


 C++言語では、関数型は次のように表されます。
extern "C" __declspec (dllexport) unsigned int function(HWND hWnd, struct ARGS *args)
 C言語では、関数型は次のように表されます。
__declspec (dllexport) unsigned int function(HWND hWnd, struct ARGS *args)
 hWnd は、編集ダイアログのウィンドウハンドルです。
 (:tryの中から呼び出されたときは、「いじくるつくーる」自身のウィンドウハンドルが渡されます)
 args は、引数を格納した構造体へのポインタです。

 R-Scriptでは、args は、次のように定義されています。
typedef struct {			/* 整数型配列 */
	char *name;		// 配列変数の名前
	unsigned int num;		// 配列の要素数 ( 0 〜 num-1 の要素番号が利用可能 )
	unsigned int *pinteger;	// 配列の先頭ポインタ
} VARIABLE_A, *PVARIABLE_A;

typedef struct {			/* 文字列型配列 */
	char *name;		// 配列変数の名前
	unsigned int num;		// 配列の要素数 ( 0 〜 num-1 の要素番号が利用可能 )
	char **ptext;		// 配列の先頭ポインタ
} VARIABLE_D_A, *PVARIABLE_D_A;

struct ARGS {  /* List of Arguments  */
	struct ARGS *next;			// 次の引数へのポインタ(リスト)
	char type;			// データタイプ UFCT_ARG_INT:0以上の整数, UFCT_ARG_STRING:文字列, UFCT_ARG_INTS:整数配列, UFCT_ARG_STRINGS:文字列配列
	union VL {
		unsigned int	integer;	// 0以上の整数型配列を入れる場合に使われる
		char		*text;	// 文字列を入れる場合に使われる
		PVARIABLE_A	pva;	// 整数を入れる場合に使われる
		PVARIABLE_D_A	pvda;	// 文字列配列を入れる場合に使われる
	} v;
};

 いわゆる「線形リスト」の方式で、各引数が格納されていきます。

 args->type は第1引数の型です。typeが0だと数値型、1だと文字列型、2だと数値型配列、3だと文字列型配列を、それぞれ表します。
 args->v は第1引数の値です。typeが0だと integer、typeが1だと text、typeが2だと pva、typeが3だと pvda が、それぞれ用いられます(数値型配列、文字列型配列の取り扱い方については「7. 引数の扱い方」を参照して下さい)。
 args->next は第2引数を格納した構造体へのポインタを表します。
 つまり、args->next->type が第2引数の型、args->next->v が第2引数の値、args->next->next が第3引数を格納した構造体へのポインタを表します。

 ここで、引数が終わる場合は、ポインタがNULLになります。
 例えば、引数が第2引数で終わる場合には、args->next->next が NULL になります。
 引数が第1引数で終わる場合には、args->next が NULL になります。
 関数が引数を渡されなかった場合は、args が NULL になります。

 DLL呼び出しされる関数側では、与えられた引数を適切に判断し、間違っている場合は処理を停止するなどの適切な処理をしなければなりません。
 (必ずしも望ましい形で引数が与えられているとは限りません。例えば、スクリプト作成者が引数の数や型を誤って渡すことがあるかもしれません。この場合、エラーであることをデバッグ中のスクリプト作成者に通知するような処理を行わなければならないでしょう)

 返したい返却値は、そのまま return で返します。


4. 文字列型を返却値とする関数の呼び出し


 C++言語では、関数型は次のように表されます。
extern "C" __declspec (dllexport) HGLOBAL function(HWND hWnd, struct ARGS *args)
 C言語では、関数型は次のように表されます。
__declspec (dllexport) HGLOBAL function(HWND hWnd, struct ARGS *args)
 hWnd は、編集ダイアログのウィンドウハンドルです。
 (:tryの中から呼び出されたときは、「いじくるつくーる」自身のウィンドウハンドルが渡されます)
 args は、引数を格納した構造体へのポインタです。引数の構造体については、前項を参照して下さい。

 返却値(文字列型)は、GlobalAlloc() APIGMEM_MOVEABLE フラグを使って呼び出して生成されるハンドルを利用して返されます。
 GlobalAlloc() APIGMEM_MOVEABLE で必要なメモリを確保し、中にヌル文字で終わる文字列を入れたら、必ず GlobalUnlock() をしてから返して下さい。

 R-Scriptインタプリタは、ハンドルを受け取ると、ただちに自身のメモリにコピーし、ハンドルを解放します。


5. スクリプトからDLL内関数を呼び出す方法


 スクリプトからDLL内関数を呼び出すには、CallDll() 関数または CallDll$() 関数を使います。
 具体的には、数値を返却値とするDLL内関数を呼び出したい場合は、
CallDll( "DLLファイル名", "関数名", 引数... )
 文字列値を返却値とするDLL内関数を呼び出したい場合は、
CallDll$( "DLLファイル名", "関数名", 引数... )
 この際、dllファイル名は英大小文字を区別しませんが、関数名は英大小文字を区別します。

 このように、通常は CallDll() 関数を使うわけですが、DLL関数を多用すると、スクリプトの見た目が悪くなるという欠点があります。
 そこで、DLLのファイル名と関数名を . (ドット) で区切って表現する方法で、DLL関数を呼び出すことができます。

 指定の仕方は、例えば MOUSE_ANIME.DLL 内の call_spi() という関数を呼び出したければ、
mouse_anime.call_spi(引数)
 というように指定します。
 DLLファイル名の方に、拡張子DLLは入れません。

 上記の例は、戻り値が数値の場合で、戻り値が文字列の場合は、関数名の後ろに$を追加しておきます。


6. DLLのアンロード


 R-Scriptは、ダイアログが閉じられた時点で、DLLをアンロードします。


7. 引数の扱い方


 関数の呼び出し方の解説で、1つめの引数には args->v、2つめの引数には args->next->v … と書きましたが、いじくるつくーるのソースに付属している rsc_calldll.h では、これらを ARG1ARG2ARG9 とアクセスできるようなマクロが定義されていますので、引数の数が多い場合は、これを使うことをおすすめします。

 以降、各引数は ARGx と表します。

 引数の型が整数配列の場合、ARGx.pva が、引数の型が文字列配列の場合、ARGx.pvda を使うことになります。
 具体的には、次のようになります。
 ARGx.pva->name … 変数名(書き換えないで下さい)
 ARGx.pva->num … 整数型配列の要素数
 ARGx.pva->pinteger[n] … 整数型配列の各要素( n = 0 〜 num-1 )

 ARGx.pvda->name … 変数名(書き換えないで下さい)
 ARGx.pvda->num … 文字列型配列の要素数
 ARGx.pvda->ptext[n] … 文字列型配列の各要素( n = 0 〜 num-1 )

 なお、未宣言の配列変数を与えられた場合、ARGx.pva には NULL が代入された状態で渡されます。


8. 返却値を間違えてDLL関数の呼び出しを行ってしまった場合


 DLLの呼び出しでは、戻り値の型を確認することができません。
 そのため、R-Script内で文字列を返却値とする関数に$をつけなかったり、逆に数値を返却値とする関数に$をつけてしまった場合、エラーとして検出されず、予期しない動作をすることになります。



 目次
 R-Scriptについて
 R-Scriptの文法


※このページは、ソフトウェアに付属のヘルプファイルをWeb用に再構築したものです。大部分に自動変換を施しているため、一部は正しく変換しきれずに表示の乱れている箇所があるかもしれませんが、ご容赦下さい。また、本ドキュメントはアーカイブドキュメントであり、内容は「いじくるつくーる」最終公開時点、あるいは、それより古い時点のものとなっております。一部、内容が古くなっている箇所があるかと思いますが、あらかじめご了承下さい。
※このページへは、自由にリンクしていただいてかまいません。

■このページに関するご意見をお待ちしております → フィードバックページ

/トップ/いじくるつくーる/ダウンロード/WebHelp/ヘルプトップ/