構造体の内容を変数にコピーする
ホストコンピュータに固定長のデータを渡すテキストファイルを作成する場合に便利なテクニックです。
構造体の内容を変数にコピーしてPrint #ステートメントでファイルに出力することができ、コーディングの手間を省けます。このテクニックは構造体の各要素がすべて文字型の場合のみ使用したほうが良いと思います。構造体の要素が整数型の場合など文字型以外の場合、各要素の内容が壊れる可能性があります。
これは、VBが文字型内部表現をUnicodeで持っているため、DLLに引数を渡す時に、UnicodeからANSIに変換してしまうからと思われます。(DLLの引数の型がAnyの場合でも変換されるようです)
サンプル(32bit)
'構造体コピーAPI Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long) Type TUHAN_SYSTEM_REC KUBUN As String * 1 HYAKATEN_ID As String * 2 HAGAKI_NO As String * 12 DEN_NO As String * 12 TODO_NAME As String * 40 TODO_KANA_SEI As String * 10 TODO_KANA_NEI As String * 10 TODO_YOU As String * 8 TODO_ADD1 As String * 40 TODO_ADD2 As String * 40 TODO_ADD3 As String * 40 TODO_TEL1 As String * 5 TODO_TEL2 As String * 4 TODO_TEL3 As String * 4 IRA_NAME As String * 40 IRA_KANA_SEI As String * 10 IRA_KANA_NEI As String * 10 IRA_YOU As String * 8 IRA_ADD1 As String * 40 IRA_ADD2 As String * 40 IRA_ADD3 As String * 40 IRA_TEL1 As String * 5 IRA_TEL2 As String * 4 IRA_TEL3 As String * 4 FILLER As String * 21 End Type Public TUHAN_SYSTEM As TUHAN_SYSTEM_REC Private Sub EXPORT_SYORI() Dim sDATA As String 'データレコード出力 sDATA = Space(Len(TUHAN_SYSTEM)) Call CopyMemory(ByVal sDATA, TUHAN_SYSTEM, Len(TUHAN_SYSTEM)) Print #1, sDATA End Sub
サンプル解説
CopyMemory関数で構造体の内容を変数 sDATA にコピーしています。
引数は次の通りです。
(引数の名前は、Declare Functionで指定したものです)
メンバー I/O 説明 Destination In コピー先の変数、または、構造体名 Source Out コピー元の変数、または、構造体名 Length In コピー元のサイズ。(バイト数) 引数を渡す場合に注意する点があります。変数の場合はByValを付けて値渡しをする必要があります。逆に、構造体の場合は参照渡しにする必要があります。
また、コピー先が変数 sDATA のように可変長の場合、あらかじめ領域を確保する必要があります。
サンプルでは、sDATA = Space(Len(TUHAN_SYSTEM))で構造体のサイズ分スペースを代入しています。また、引数の説明でも判るように、変数の内容を構造体にコピーする事も可能です。
ただし、この場合、1つ注意する点があります。
変数内に漢字が存在した場合、コピー後、漢字の入った構造体の要素の前の要素の末尾にゴミが入る場合があります。この要素は固定長の指定した長さより大きくなっており、大きくなった部分にゴミが入ります。この状態になったら、Left関数などで大きくなった部分を切り捨てる必要があります。(一旦、ANSIに変換してLeftB関数でバイト単位に切り捨てるほうがバグの原因になりにくいのでお勧めです。切り捨て後、再びUnicodeに変換すればOKです)
(各要素は大きくなるだけで、内容は正常です)これは、VBが引数の内容をUnicodeからANSIに変換してDLLに渡し、DLLがメモリ(この場合は引数の内容)をコピーして、再びVBに戻りANSIからUnicodeに変換しているのですが、物が構造体だけにANSIからUnicodeの変換に漢字が入ると不具合が生じるみたいです。
また、引数DestinationやSourceは実際はポインタなので、APIで得たポインタが示す値を取得したりなど、値←→ポインタの相互変換もできます・・・。
(例えば、DEVMODE構造体の入出力に利用できたりします)
[ Window Close ]