ENGLISH

32 ビット版 Visual Basic
使用時におけるバイトアライメントの問題

ポジションブロックの問題とともに、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 などでキーバッファに数値をセットしなければならない時も、同様の処理が必要になります。

Contactお問い合わせ

お気軽にお問い合わせください。

お問い合わせ

    必須会社名

    個人のお客様は「個人」と入力してください。

    必須お名前
    必須メールアドレス
    必須メールアドレス(確認)
    必須ライセンス ありなし
    ダウンロード目的