HSP用プラグインは要するにDLLのなので作成方法そのものは通常のDLLとほとんど変わりません。
通常のDLLと違う点は、エクスポートテーブルへの登録がPROCディレクティブにEXPORTを指定するだけで良い点です。通常のDLLの様に定義ファイル(.DEF)を作成する必要がありません。これはHSPがGetProcAddressに渡すプラグインの関数名をSTDCALLの名前付け規約そのままで使用しているためです。
DLLのエントリポイント(実行開始地点)はDllMain(名前は変更可能)で、プロセスへのアタッチやデタッチ時に呼び出されます。つまり、ここで初期化処理や終了処理を行います。
DllMainの説明(MSDN Online)
プラグインの関数にはいくつかのタイプがあり、その内容はHSPからのDLL呼び出し方法リファレンスマニュアルに書かれています。関数に渡される引数は4つと固定されていて、その内容は選択したタイプによって決まります。HSPスクリプト側から渡せるパラメータは、タイプ$202以外は2〜4個で、その数と種類はタイプによって固定されています。タイプ$202ではスクリプト側から渡せるパラメータの数や種類に制限はありませんが、Ver2.6から新設されたタイプなので、それ以前のHSPではサポートされていません。
返値は通常0にしますが、システム変数statに値を返したい場合は負の数を返します。エラーを表示したい場合は1〜255の値を返すと、それに応じたエラーメッセージが表示されて終了します。他にも関数終了後にawait・waitを実行させることも出来ます。
サンプルとして、日付をタイトルとしたMessageBoxを表示する命令を、タイプ6と$202で作成します。
;********************************************************************* ;タイトルに日付を持つMessageBoxを表示 ;TestProc p1,p2 ;TestProc2 p1,p2 ;p1:メッセ−ジ ;p2:MessageBoxのタイプ ;********************************************************************* .386 .model flat,stdcall option casemap:none include windows.inc include hspdll.inc include kernel32.inc include user32.inc includelib kernel32.lib includelib user32.lib ;********************************************************************* .data fmt db "%04d年%02d月%02d日",0 .code ;********************************************************************* DllMain PROC ,hInstDLL:HINSTANCE, fdwReason:DWORD, lpvReserved:LPVOID mov eax,TRUE ret DllMain ENDP ;********************************************************************* TestProc PROC EXPORT,pBms:ptr BMSCR, pMsg:ptr CHAR ,uType ,tmp ;type 6 LOCAL stime:SYSTEMTIME ,date[SIZEOF fmt]:CHAR invoke GetLocalTime,ADDR stime movzx eax,stime.wYear movzx ecx,stime.wMonth movzx edx,stime.wDay invoke wsprintf,ADDR date,ADDR fmt,eax,ecx,edx mov ecx,pBms invoke MessageBox,[ecx].BMSCR.hwnd,pMsg,ADDR date,uType neg eax ret TestProc ENDP ;********************************************************************* TestProc2 PROC EXPORT USES ebx ,pExinfo:ptr HSPEXINFO, tmp1,tmp2,tmp3 ;type$202 LOCAL stime:SYSTEMTIME ,date[SIZEOF fmt]:CHAR ,pMsg ,uType invoke GetLocalTime,ADDR stime movzx eax,stime.wYear movzx ecx,stime.wMonth movzx edx,stime.wDay invoke wsprintf,ADDR date,ADDR fmt,eax,ecx,edx mov ebx,pExinfo ASSUME ebx:ptr HSPEXINFO invoke [ebx].HspFunc_prm_gets mov pMsg,eax invoke [ebx].HspFunc_prm_getdi,MB_OK mov uType,eax mov ecx,[ebx].er mov eax,[ecx] .if eax ret .endif mov eax,[ebx].actscr invoke [ebx].HspFunc_getbmscr,DWORD ptr [eax] mov ecx,eax ;eaxはスタック変数のアドレス取得に使われる invoke MessageBox,[ecx].BMSCR.hwnd,pMsg,ADDR date,uType neg eax ret TestProc2 ENDP ;********************************************************************* END DllMain
@ECHO OFF Ml /c /coff TestHpi.asm if errorlevel 1 goto error Link /SUBSYSTEM:WINDOWS /DLL TestHpi.obj if errorlevel 1 goto error goto fin :error echo ===============================エラー====================================== :fin echo ===============================終了=======================================
#uselib "TestHpi.dll" #func TestProc TestProc 6 #func TestProc2 TestProc2 $202 #define MB_ICONERROR $00000010 #define MB_ICONQUESTION $00000020 testproc "test1",MB_ICONERROR testproc2 "test2",MB_ICONQUESTION
タイプ$202では必要な情報は全てHSPEXINFO構造体を通じて入手します。つまり何度もHSPEXINFO構造体にアクセスする必要があり、よけいな手間を省くためには、そのアドレスをebxなどの値が保存されるレジスタに格納しておき、ASSUMEディレクティブで型を指定しておきます。