- PR -

VB.NETからアンマネージDLLの呼び出し

1
投稿者投稿内容
nico
会議室デビュー日: 2004/07/17
投稿数: 6
投稿日時: 2004-07-17 10:50
VB.NETからC/C++で作成したアンマネージDLLを呼び出しているんですが、
うまくいきません。
具体的には、VB側で下記のような構造体のbufferの部分にバイト配列を割り
当てて、DLLのパラメータとして渡し、DLL内でbufferで指定されるメモリ
領域に データを書込むような動作を行いないたいです。
MSDNのヘルプを見ていろいろと試してみましたが、DLL呼び出し部で異常と
なってしまいます。

構造体をどう宣言すればよいのでしょうか?

struct A {
char* buffer ;
......
} ;
※ ちなみに、bufferは文字列ではなく、単なるバイトの配列として扱い、 
  やり取りするデータのサイズは100k byte 程度です。


VB.net側では、下記の構造体とDLL宣言で試してみましたが例外(MarshalDirectiveException)が発生します。

<StructLayout(LayoutKind.Sequential)> _
Public Structure A
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=100000)> _
Public buffer As Byte()
......

Sub Initialize
  ReDim buffer(100000)
End Sub
End Structure


Declare Auto Function Proc Lib "xxxxx.dll" ( ByRef reply As A ) As Integer

構造体のサイズが大きすぎる?というエラー内容なので、サイズを小さく(1000byteくらいに)してみると、MarshalDirectiveExceptionは発生しなくなりますが、データコピー時にNullReferenceExceptionとなります。
Jubei
ぬし
会議室デビュー日: 2002/03/02
投稿数: 830
お住まい・勤務地: 関西
投稿日時: 2004-07-17 17:48
諸農です。

GDNJでの投稿者と同じ人かと思いますが。。

DLL側で宣言されている関数はどのようなものでしょうか。
また、元々定義されている構造体宣言はどのようなものでしょうか?

関数の引数タイプにもよるかと思いますが、構造体を渡すのであれば
Marshal.StructureToPtr()は使えませんか?

ちなみにGDNJではコメントが付いていますが、その結果はどうなっていますか?


_________________
諸農和岳
Powered by Turbo Delphi & Microsoft Visual Studio 2005

十兵衛@わんくま同盟
http://blogs.wankuma.com/jubei/
nico
会議室デビュー日: 2004/07/17
投稿数: 6
投稿日時: 2004-07-27 01:02
Jubeiさん、こんにちは。
なかなか時間が取れなくて返事が遅れてすみません。
nicoです。(おっしゃるとおりGDNJで質問したものです)


DLL側の関数宣言は、こんな感じです。
long func( struct TYPE_A* param )


ちなみにGDNJのコメントのとおりに構造体内のchar* を IntPtrに置き換えてみて、
Marshal.AllocHGlocal/AllocCoTaskMemを使ってメモリを割り付けてみたところ、
一応思い通りの動作をするようにはなりました。
(ここまでたどり着くのにかなり時間がかかってしまいましたが)

しかし、上記のメソッドでメモリを割り付けるという方法が何となくですが、
しっくりきません。
ちゃんと解放すれば問題ないんでしょうが、なんかメモリリークとか起こしそうで。

他にベストな方法(一般的な方法)をご存知でしたら、教えていただきたいです。


[ メッセージ編集済み 編集者: nico 編集日時 2004-07-27 01:07 ]
Jubei
ぬし
会議室デビュー日: 2002/03/02
投稿数: 830
お住まい・勤務地: 関西
投稿日時: 2004-07-27 02:09
諸農です。

引用:

ちゃんと解放すれば問題ないんでしょうが、なんかメモリリークとか起こしそうで。



メモリリークですか?
Marshal.FreeHGlobalしていないのでしょうか?

引用:

他にベストな方法(一般的な方法)をご存知でしたら、教えていただきたいです。



.NETではない、その関数が元々想定していたアンマネージドな
方法が一番ベストなのでは?アンマネージド←→マネージドを
橋渡しするのであれば仕方のないことかも知れませんし、元々
想定されている呼び出しでも、メモリの確保をしているんじゃ
ないですか?それともメモリの確保無しで呼び出しが可能な関
数なんですか?

う〜〜ん、何を訴えられているのか、いまいちピンときません。


_________________
諸農和岳
Powered by Borland Delphi/C++Builder & Microsoft VS.NET

[ メッセージ編集済み 編集者: Jubei 編集日時 2004-07-27 02:11 ]
nico
会議室デビュー日: 2004/07/17
投稿数: 6
投稿日時: 2004-08-04 00:18
どうも、nicoです。

FreeHGlobalすればメモリリークしないことは分かってるんですが、
メモリのことを意識しなくてもよいコード(ガベージコレクションでメモリ解放してくれる
コード)とメモリの解放を意識しなければいけないコード(メモリリークの可能性がある
コード)が混在するのが、なんとなく嫌だなと思っただけです。

その後、ヘルプを調べて見た結果、Marshal.UnsafeAddrOfPinnedArrayElement で、
マネージコードの配列のアドレス(IntPtr)を取得できるようなので、それを構造体の
IntPtr型のメンバに割り当てて、アンマネージDLLへ渡すことで解決することにしました。

長々と付き合っていただき、どうもありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)