HSPのモジュール機能を活用してみる ACT-2

グローバル領域へのアクセス

グローバル変数の読み書き

変数名の独立性が売りのモジュール機能ですが、やっぱりどうしてもモジュールの外の変数にアクセスしたいときもあるわけです。今回は、その方法を紹介しましょう。モジュール内をモジュール空間と呼ぶのに対して、ここでは、モジュールの外部をグローバル空間(領域)と呼び、モジュールの外部の変数をグローバル変数と呼ぶことにします。

モジュール内部からグローバル変数にのデータを読み書きするには、変数の後ろにアットマーク(“@”)を付けるだけで実現されます。

#module

#deffunc myfunc1
temp  = 20            ; モジュール変数
temp@ = 30            ; グローバル変数
mes "---------モジュール---------"
mes "temp  = " + temp
mes "temp@ = " + temp@
mes "----------ここまで----------"
return

#global

temp = 10
mes "temp  = " + temp
myfunc1
mes "temp  = " + temp
stop

グローバル領域あるいは他のモジュール領域から別のモジュール内の変数にアクセスすることも可能ではあります。この場合は変数名の後ろに“@モジュール名”をつけることで実現できます。例えば、sizex@subとすると、subという名前のモジュール内のsizexという変数を指します。しかしこの手法はあまりお勧めできません。なぜならプログラムの構造を複雑にしてしまう危険性があるからです。使うとしても、モジュール内の変数の値を初期化するなどの目的でアクセスする程度にとどめておいたほうがいいでしょう。

拡張DLL命令の実行

さて、変数はその変数の割り当てられているモジュール領域あるいはグローバル領域内のみで有効で、他の領域からアクセスするには上で述べたような手法を使わなければなりませんでした。ところが、変数以外にもそのようなものがあります。それは何かと言うと、「#funcで定義された拡張DLL命令」なのです。

したがって、グローバル領域で#func定義された拡張DLL命令をモジュール領域で使うには、命令名のあとにアットマーク("@")をつけるか、あるいはモジュール内で再び#func定義をしなければなりません。たいていの拡張DLLはヘッダファイルで#func定義をしているので、モジュール内で再び#includeを実行すれば大丈夫ですが、#func定義による拡張プラグイン命令の定義のほかに、同じファイル内でモジュールの定義などもされている場合には、他のモジュール内でそのファイルをインクルードするとエラーになってしまいます。そのため、そのような拡張命令をモジュール領域内から実行させるには、アットマークをつける方法を使わなくてはなりません。

定数名の参照

モジュール領域とグローバル領域で区別されるものがさらにあともう1つあります。それは、「#defineまたは#constによって定義されたマクロ名・定数名」です。これらの命令によってグローバル領域でマクロ定義された定数などをモジュール領域で使用するためには、やはり定数名にアットマークをつけねばなりません。

ただし、HSP Ver2.6以降では、#define#const命令に対して、グローバル指定子globalが導入されており、これとともに指定されたマクロ名・定数名はグローバルマクロ名・定数名として、どのモジュール領域からも同じ名前で記述することができるようになっています。

llmodモジュールでは、あらかじめロードされているDLLを識別する値として以下のような定数名をグローバル指定子global付きで定義しています。

#define global  D_KERNEL      0
#define global  D_USER        1
#define global  D_SHELL       2
#define global  D_COMCTL      3
#define global  D_COMDLG      4
#define global  D_GDI         5

これらの定数名は主にモジュール命令dllprocで使用しますが、グローバル領域でもモジュール領域内でも「D_USER」のように、アットマーク無しで指定することができます。

dllproc "MessageBoxA", pm, 4, D_USER

また、global指定子が導入される以前のバージョンとの互換性を保つために、アットマークを付けても、同じように動作するようになっています。

dllproc "MessageBoxA", pm, 4, D_USER@