さて、実際にスクリプトを書いてみましょう。
各処理の部分に分けて見ていくことにします。
#include "llmod.as"
#include "apierr.as" ; エラーコード取得モジュール
screen 0, 300, 224
onexit *lb_quit ; 終了時にジャンプ
name = "HSP_mem_Test" ; ファイルマッピングオブジェクトの名前
; ファイルマッピングオブジェクトの作成
prm.0 = -1 ; 0xFFFFFFFF
prm.1 = 0 ; NULL
prm.2 = 4 ; PAGE_READWRITE
prm.3 = 0
prm.4 = 1024 ; ファイルマッピングオブジェクトのサイズ
getptr prm.5, name ; オブジェクト名のアドレス
dllproc "CreateFileMappingA", prm, 6, D_KERNEL
hmapobj = dllret
; オブジェクトが作成されていたかどうかの判別
geterrcode ; GetLastError関数によるエラーコード取得
if stat == 183 { ; ERROR_ALREADY_EXISTS
goto *lb_exist ; すでに同じ名前のマッピングオブジェクトが
; 存在する場合
} else {
goto *lb_new ; マッピングオブジェクトが存在しない場合
}
まずはマッピングオブジェクト作成部分です。
今回はメモリ上にマッピングオブジェクトを作成するためにCreateFileMapping関数の第1引数に0xFFFFFFFF (-1) を指定しています。ここでは共有メモリのサイズを1024バイトにしてあります。
マッピングオブジェクトを識別できるように、固有の名前を作成するオブジェクトにつけます。すでに同じ名前のマッピングオブジェクトがあるかどうかは、CreateFileMapping関数呼び出し直後にGetLastError関数を呼び出して、その戻り値を調べることでわかります。戻り値が183であれば、すでに同じ名前のマッピングオブジェクトが存在していることになります。
今回は、GetLastError関数を呼び出すのに、『Win32 APIのエラー処理』の項で作成したエラーコード取得モジュールapierr.asの中のgeterrcode命令を使用しています。このgeterrcode命令は、GetLastError関数を呼び出して、取得されたエラーコードをstatに格納します。したがって、このapierr.asをインクルードしておく必要があります。
; 新規に共有メモリをセット
*lb_new
sdim buf, 1024
mesbox buf, 300, 200, 1
objsize 100
button "書き込み", *lb_setmem
stop
*lb_setmem
; ビューのマッピング
prm.0 = hmapobj ; マッピングオブジェクトのハンドル
prm.1 = 2 ; FILE_MAP_WRITE
prm.2 = 0
prm.3 = 0
prm.4 = 0
dllproc "MapViewOfFile", prm, 5, D_KERNEL
lpdata = dllret ; 先頭アドレス
ll_poke buf, lpdata ; 共有メモリ領域に文字列をコピー
prm = lpdata
dllproc "UnmapViewOfFile", prm, 1, D_KERNEL
dialog "共有メモリに書き込みました。"
stop
まだ共有メモリが作成されていなかった場合の処理です。1回目の起動ではこの処理がなされます。HSPのメッセージボックスに文字列を入力して、ボタンを押せば共有メモリにその内容が書き込まれるようにしてあります。
MapViewOfFile関数を実行すると、データ領域の先頭アドレスが返されるので、loadlibメモリアクセス命令ll_pokeを用いてそのアドレスに書き込みます。
ここではマップしてからアンマップするまでの処理を一度に行なっていますが、アンマップのし忘れを防ぐためにも、このようにしたほうがいいでしょう。
; すでに共有メモリが存在していた場合
*lb_exist
sdim buf, 1024
prm.0 = hmapobj ; マッピングオブジェクトのハンドル
prm.1 = 4 ; FILE_MAP_READ
prm.2 = 0
prm.3 = 0
prm.4 = 0
dllproc "MapViewOfFile", prm, 5, D_KERNEL
lpdata = dllret ; 先頭アドレス
ll_peek buf, lpdata ; 共有メモリ領域から文字列を読み込む
prm = lpdata
dllproc "UnmapViewOfFile", prm, 1, D_KERNEL
mesbox buf, 300, 200, 0
stop
2回目以降の起動の場合、すなわち、すでに共有メモリが作成されていた場合は、その内容を表示するようにしています。
今回は読み出すことしかしないので、MapViewOfFile関数の第2引数には4 (FILE_MAP_READ) を指定しています。
ここではll_peek命令を使って、データの先頭アドレスから変数に読み込んで、その内容をメッセージボックスで表示しています。
; 終了処理(マッピングオブジェクトのハンドルのクローズ)
*lb_quit
if hmapobj {
prm = hmapobj
dllproc "CloseHandle", prm, 1, D_KERNEL
}
end
終了時に実行される処理です。CloseHandle関数を呼び出してマッピングオブジェクトのハンドルをクローズし、オブジェクトの破棄を行ないます。実際にはすべてのプロセスがクローズしない限り、マッピングオブジェクトは破棄されません。