Contactお問い合わせ
お気軽にお問い合わせください。
ポジションブロックの問題とともに、Visual Basic (32bit) で Btrieve API を使用する場合にトラブルの原因となるのが、バイトアライメントの問題です。
バイトアライメント自体は VB に限らず他の言語でも行われていることですが、VB 以外の言語ではコンパイル時のオプション指定などで、トラブルの発生を防ぐことができます。
Visual Basic (32bit) の中でユーザ定義型(他の言語では構造体とかレコード型と呼ばれる)を使用すると、VB によってバイトアライメントが実行されます。
具体的には、ユーザ定義型の中で数値変数が使われていると、処理の最適化のために、数値変数が 4 バイトごとの境界にくるよう VB が内部的に余分なバイトを挿入します。
Type DataBuffer
Field1(0 To 1) As Byte
Field2 As Long
Field3 As String * 10
End Type
これが内部的には、
Type DataBuffer
Field1(0 To 1) As Byte
Field2 を 4 バイトの境界に動かすために、ここに余分な 2 バイトが挿入される
Field2 As Long
Field3 As String * 10
End Type
となってしまいます。
プログラマからこうしたことは見えませんが、VB の中だけで処理がすむのであれば、もちろん問題が表面化することはありません。
しかし、外部の DLL などとデータの受け渡しを行う場合は、問題になってきます。
Btrieve アクセスの場合でいうと、データバッファをユーザ定義型で宣言し、Btrieve API を使ってレコードを読み込むとき、Btrieve は 2 バイト分広がった入れ物に対して、それとは知らずにデータを流し込んできます。
結果として、Field-1 は正しく読み込めますが、Field-2 は本来のデータである 4 バイト長整数の後ろ 2 バイト分と Field-3 の先頭 2 バイト分で構成され、Field-3 には本来のデータから先頭 2 バイトを除いたデータが格納されているかのように見えてしまいます。
Btrieve はレコードの内容には一切手を加えません。それがどのような言語で書き込まれたものか、フィールドがどうなっているのか、どのようなデータ型であるのか、といったことには関知しません。単なるバイトの並びとして扱うだけです。データバッファに入っている通りをそのままファイルに書き出し、または読み出してアプリケーションに渡します。
Visual Basic (32bit) におけるバイトアライメントの問題を解決するためには、Btrieve とのデータ受け渡しにバイト型配列を使うことです。
Type DataBuffer
Field1(0 To 1) As Byte
Field2 As Long
Field3 As String * 10
End Type
ではなく、
Type DataBuffer
Field1(0 To 1) As Byte
Field2(0 To 3) As Byte
Field3 As String * 10
End Type
このように定義します。
しかしこのままでは、Field-2 を VB 内で数値として扱えないので、バイト配列と数値変数間の変換処理が必要になります。VB にはメモリ間のコピー機能がないので、たとえば WindowsAPI を使って実現します。
Declare Sub CopyMemory Lib “kernel32” Alias “RtlMoveMemory” ( _
hpvDest As Any, _
hpvSource As Any, _
ByVal cbCopy As Long)
Dim SampleDataBuffer As DataBuffer
Dim lngField2Value As Long
CopyMemory lngField2Value, SampleDataBuffer.Field2(0), 4
これで lngField2Value が本来の長整数型の数値として扱えるようになります。
データを書き出す場合は、逆に、
CopyMemory SampleDataBuffer.Field2(0), lngField2Value, 4
として、Btrieve に渡すデータバッファのバイト配列に正しくデータをセットします。
ユーザ定義型の中で数値変数(Integer, Long, Single, Double, Currency など)を使用する場合は、すべてこの処理が必要です。
また当然ですが、Get Equal などでキーバッファに数値をセットしなければならない時も、同様の処理が必要になります。