ActiveBasic 3.1
Basic特有「文字列変数」について

N88BASIC時代から、文字列を1つの変数として扱うという概念が存在しました。その概念はActiveBasicでも継承されますが、残念ながら、Win32APIなどのDLL関数とのインターフェイス(関数パラメータ、戻り値)として利用することはできません。String型の利用を控える必要があるケースは、以下のとおりです。

ActiveBasicのString型と外部DLL関数の管理方法に相違点があることから、このような制限がかけられます。String型は内部でメモリ領域の確保、解放などの管理がなされているのに対し、外部DLLでは、バイト配列の先頭ポインタを文字列変数の代わりとして採用します。外部DLLにより、String型変数の内容(文字列を示すポインタデータ)が書き換えられると、本来の文字列データの解放処理が正常に行われず、メモリアクセスエラーになったり、文字列用に確保されたメモリが未解放のまま放置されることになります。String型は、対象プログラムの内部でのみの利用であれば、以前のように扱うことはできますが、上記のようなケースに対しては、BytePtr型を利用して下さい。

BytePtr型の特徴

BytePtr型はC言語で言う(char *)などにあたります。NULLで終わる文字列データ(バイト配列)の先頭ポインタを格納するための変数です。

Dim a As BytePtr
a = "test"
a = "test" + "123"

いきなりですが、上のプログラムは3行目で文法エラーとなります。右辺で文字列演算が行われることが理由に挙がります。しかし、何故か2行目はエラーになりません。これは、"test"という文字列を示すポインタが変数aに格納されるからです。文字列領域の確保、解放処理、および文字列の連結処理が必要ないため、このような操作を行うことができます。この操作はC言語でも許されており、以下のようなプログラムを見たことがある方もいるのではないでしょうか?

char *a;
a = "test";

BytePtr型変数が示す文字列データに対して、連結処理を行いたいときは、wsprintf関数などが有効的です。

Dim a As BytePtr
a = HeapAlloc(GetProcessHeap(), 0, 256)
wsprintf(a, "%s%s", "test", "123")
MessageBox(0, a, "BytePtr型を用いた文字列連結テスト", MB_OK)
HeapFree(GetProcessHeap(), 0, a)

ここでポイントとなるのは、メモリ確保、解放の処理を忘れずにおこなう点です。BytePtr型を用いて、文字列データを操作する場合は、常に、文字列データがどのようなメモリ領域に格納されるのかを把握しておく必要があります(これらの操作を暗黙にやってくれるのがString型です)。

String型→BytePtr型

String型からBytePtr型への変換は、「String型が管理する文字列の先頭ポインタをBytePtr型変数に格納する」という操作を行うことで可能になります。

Dim a As String
Dim b As BytePtr
a = "test" + "123"
b = StrPtr(a)
MessageBox(0, b, "String型からBytePtr型への変換テスト", MB_OK)

"b = a"という演算は型違いのエラーになるので、StrPtr関数を利用し、文字列ポインタを取り出す操作を行います。

String型←BytePtr型

こちらは非常に簡単です。

Dim b As BytePtr
b = "test"
a = b + "123"
MessageBox(0, a, "BytePtr型からString型へのテスト", MB_OK)

4行目のように、BytePtr型は文字列演算の一部に取り入れることが可能です。