さて、そろそろ皆さん、あのテンプレートがうざくなってきた所ではないでしょうか (爆)。結構面倒ですよね。あれ。
というわけで、今回はあのテンプレートを使わずに、プラグインを作ろうではないかという話です。
あのテンプレートが必要になるのは:
……くらいです ( うん、多いですよ? )。
実は、そこそこのことは Dll 呼び出しでもできます。これは厳密には HPI ではないのですが、他に正式な呼び名がないようなので、DllHPI とでも言っておきましょう。
さて、作り方です。まずはざっくりと簡単なモノを見てください。
#include <windows.h>
EXPORT void WINAPI msgboxA(void)
{
MessageBoxA( 0, "Hello, world!", "dllhpi", MB_OK );
return;
}
※DllMain() は省略できる、のか? なくても動いてしまうが。
このソースファイルだけでビルドできます ( 出力ファイルを test.hpi とします )。
次に、HSP側のヘッダを。
#ifndef IG_DLLHPI_TEST_AS #define IG_DLLHPI_TEST_AS #uselib "test.hpi" #func msgbox "msgboxA" // サンプル・スクリプト #if 1 msgbox #endif #endif
※ VC++ の場合は、"msgboxA" を "_msgboxA@0" とします。
実行。ふう、やはりいつも通りの始まり方ですね、これが。
……って、これただのDll呼び出しじゃん!!
ば、ばれたか…………。たしかに、これだけだと普通に dll 呼び出しただけです、はい。
ということは、DllHPI は Dll呼び出しの延長線上にある、ということです。
DllHPI と普通のDllの違いは、呼び出し引数にあります。引数によって、HPIでおなじみのあの構造体の方々が使用できます。
| 引数タイプ | 渡される型 | 指定すべきもの |
|---|---|---|
| pval | PVal* | 変数 |
| bmscr | BMSCR* | (なし) |
| prefstr | char[] | (なし) |
| pexinfo | HSPEXINFO* | (なし) |
基本的に、「#func」のヘルプを見ればいいかと思います。
ちなみに、BMSCR 構造体は、いままで触れていませんでしたが、HSPのウィンドウを管理する構造体です。bmscr の引数は、操作先ウィンドウのそれへのポインタを渡します。これを使って、画面への描画やウィンドウの操作なども行えますので、後々やってみようと思っています。
新しくプラグインを考えるのも面倒なので、既存のモノをこの形式で作り直してみましょう。
varinfo でいいですか。いいですね。
今回のソースコードはここにあります:「varinfo (dllhpi版)」
// varinfo dllhpi
#include <windows.h>
#include "hsp3plugin.h"
#include "varinfo.h"
//------------------------------------------------
// varinfo()
//------------------------------------------------
EXPORT int WINAPI varinfo( PVal* pvTarget, int type, HSPEXINFO* pExinfo )
{
::exinfo = pExinfo;
switch ( type ) {
case VARINFO_LEN0: return pvTarget->len[0];
case VARINFO_LEN1: return pvTarget->len[1];
case VARINFO_LEN2: return pvTarget->len[2];
case VARINFO_LEN3: return pvTarget->len[3];
case VARINFO_LEN4: return pvTarget->len[4];
case VARINFO_FLAG: return pvTarget->flag;
case VARINFO_MODE: return pvTarget->mode;
case VARINFO_PTR:
{
HspVarProc* vp = getproc( pvTarget->flag );
return reinterpret_cast<int>( vp->GetPtr(pvTarget) );
}
default:
puterror( HSPERR_ILLEGAL_FUNCTION );
}
}
いつも通り "hsp3plugin.h" を結合していますが、PVal や HSPERROR などの定義はこれを使わないと分からないので、仕方がありません。
このせいで、グローバル変数 exinfo や ctx が定義されてしまうという困った事態にもなります。それらは、いつもは hspsdk_init() で初期化されていたので問題ないのですが、DllHPI ではそんなものないので、NULL です。危険です。
そこで、引数で受け取った HSPEXINFO* をセットしておきます。本当は不要ですが、これをすると puterror() などの、グローバル変数 exinfo を使用しているマクロが使えるようになります。だれも、pExinfo->HspFunc_puterror() なんて長ったらしいことはしたくないでしょう?
これのヘッダ varinfo.h は次の通りです。
// varinfo dllhpi
#ifndef IG_VARINFO_DLLHPI_H
#define IG_VARINFO_DLLHPI_H
#include <windows.h>
#include "hsp3plugin.h"
// プロトタイプ宣言
EXPORT int WINAPI varinfo( PVal* pval, int type, HSPEXINFO* pExinfo );
// 定数
enum VARINFO {
VARINFO_LEN0 = 0,
VARINFO_LEN1,
VARINFO_LEN2,
VARINFO_LEN3,
VARINFO_LEN4,
VARINFO_FLAG,
VARINFO_MODE,
VARINFO_PTR,
VARINFO_MAX
};
#endif
この2つのファイルでビルドできます。出力ファイルは varinfo.hpi とします。
そして、HSP側のヘッダは次の通り。
// varinfo - public header #ifndef IG_VARINFO_HPI_AS #define IG_VARINFO_HPI_AS #uselib "varinfo.hpi" #cfunc global varinfo "_varinfo@12" pval,int, pexinfo // 定数 #enum global VARINFO_LEN0 = 0 #enum global VARINFO_LEN1 #enum global VARINFO_LEN2 #enum global VARINFO_LEN3 #enum global VARINFO_LEN4 #enum global VARINFO_FLAG #enum global VARINFO_MODE #enum global VARINFO_PTR #enum global VARINFO_MAX // サンプル・スクリプト #if 1 // 本当はもっと入念にテストしてください (>_<; a = 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 mes "len1 : " + length(a) + "\t: " + varinfo(a(1), VARINFO_LEN1) mes "len2 : " + length2(a) + "\t: " + varinfo(a(1), VARINFO_LEN2) mes "len3 : " + length3(a) + "\t: " + varinfo(a(1), VARINFO_LEN3) mes "len4 : " + length4(a) + "\t: " + varinfo(a(1), VARINFO_LEN4) mes "ptr : " + varptr(a(1)) + "\t: " + varinfo(a(1), VARINFO_PTR ) mes "flag : " + vartype(a(1)) + "\t: " + varinfo(a(1), VARINFO_FLAG) mes "mode : " + "----" +"\t: " + varinfo(a(1), VARINFO_MODE) stop #endif
※インポート関数名 "_varinfo@12" は VC++ 2008 の場合です。BCC の場合は "varinfo" にしてください。
今回の varinfo は命令形式では使用できません。たぶん問題ないと思いますが、一応。
今回は趣向を変えて Dll 呼び出しバージョンを試してみました。
では、また次回。
by 上大