投稿者 魔界の仮面弁士  (社会人) 投稿日時 2009/1/23 18:38:46
>> ByVal String を使うのではなく、ByRef Byte を使うようにしてください。
> (あるいは、ByVal Long でポインタを指定するのも有効です)
> 仰る通りByVal Stringになっていたので、ByRef a() as Byteとしてみましたが、型か違うと怒られてしまいました…

もう一度読みなおしてみてください。私は「ByRef a() As Byte」と書いた覚えはありませんよ。

例えば、
 Declare Sub Foo Lib "dllname" (ByVal a As String)
という API 宣言があったとしたら、
 Declare Function Foo Lib "dllname" (ByRef a As Byte) As Long
   (中略)
 ret = Foo(buf(0))   'バイト配列の先頭要素をByRefで渡す
のようにする、という事です。

String 型で渡した場合、既定のコードページで ANSI/Unicode 変換が行われてしまうので、
変換せずに渡したい場合には、このように記述する必要があります。


>>  s = ChrW(&H201A)
>>  s = ChrW(32 * &H100 + 26)
> こういう設定もあったのですね、奥深いですね…
あるいは、
 Dim s As String
 s = ChrB(26) & ChrB(32)
という手もあります。Chr/ChrW/ChrB の使い分けに注意。


> (26,32)を無理やり突っ込みましたが
突っ込むのは良いですが、それを ByVal String で渡したのでは意味がありません。

API に String で渡すと、そのデータを「Unicode テキストを表すバイナリ」とみなして
規定のコードページ(日本語では CP932/Shift_JIS)に変換した上で DLL に渡されます。
そして、DLL から受け取る場合には、それを逆変換して Unicode として String に
戻そうとする設計になっているためです。

そうした ANSI/Unicode 変換を行わせず、生データを直接やりとりさせるためには、
String 型は使用せず、先に書いたように、ByRef Byte(あるいは、ByVal Long)として、
バイナリデータの先頭アドレスを渡すようにする必要があります。