- - PR -
アンマネージドメモリの確保
1
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2005-06-21 11:30
C# でアンマネージDLLのラッパークラスを作ろうとしているのですが
ローカル変数にメモリを確保する方法がわかりません。MSDNとかも調 べてみましたが、データのマーシャリングについて今ひとつよくわか りません。 どなたかご教授いただけないでしょうか? 具体的には以下のようなコードを書きたいのですが。 [C] struct sinf { unsigned char c_no; char *str; char *buff; } ; char buff[2000]; struct sinf sinf; unsigned int WINAPI Function1( struct sinf *) ; BOOL WrapFunction() { sinf.buff = buff; if( Function1( &sinf ) != 0) { return( FALSE ); } return( TRUE ); } C#では以下のように書いたのですが、 [C#] [StructLayout(LayoutKind.Sequential)] struct sinf { char no ; string str ; byte[] buff; } static sinf sinf; public class sample { [DllImport("FUNCTION.DLL")] private extern static uint Function1( ref sinf inf ); public static bool wrapFunction( ) { // ここでメモリを確保? if( Function1( ref sinf ) != 0) { return false; } return true; } } | ||||||||
|
投稿日時: 2005-06-21 13:12
以下の情報が参考になるかもしれません。
[HOWTO] Visual C# .NET でオペレーティング システムの Service Pack レベルを判断する方法 _________________ 諸農和岳 Powered by Turbo Delphi & Microsoft Visual Studio 2005 十兵衛@わんくま同盟 http://blogs.wankuma.com/jubei/ | ||||||||
|
投稿日時: 2005-06-21 14:07
説明が足りなかったみたいです。すみません。
お聞きしたかったのは構造体の中に文字列を確保するのではなく、 クラスのローカル変数としてメモリを確保して、構造体にはその アドレスを渡すというものです。 例でいうと、構造体sinfの中のbuffがローカル変数buffへのポインタ を保持している(Cプログラム参照)部分がお聞きしたかったところ です。 Cプログラムでは単に char buff[2000]; として領域を確保していますが、C#ではどうなるのでしょう? | ||||||||
|
投稿日時: 2005-06-21 14:18
同じですよ。 改訂版 C#入門 第21章 ポインタを使用できる「安全でないコード」あたりを熟読してください。 | ||||||||
|
投稿日時: 2005-06-21 20:24
私の勘違いだったらすみません。
struct sinf { char no ; string str ; [MarshalAs(UnmanagedType.ByValArry, SizeConst = 2000)} byte[] buff; } となるということでしょうか。 しかし、これだと構造体中に2000バイトの配列が確保されてしまいませんか? | ||||||||
|
投稿日時: 2005-06-21 22:43
本当に読んだ?
C#にもポインタ変数があります。fixedやunsafeを使えばC++と同じように
見たいなコードを記述することが出来ます。
とかでも出来そうな気がしますが、未確認です。 | ||||||||
|
投稿日時: 2005-06-21 23:11
.NETにおけるポインタ/ハンドル用の型はSystem.IntPtr構造体です。
メモリ確保はSystem.Runtime.InteropServices.Marshal.AllocHGlobalで行い、 System.Runtime.InteropServices.Marshal.FreeHGlobalで解放します。 バイト配列との相互コピーやデータの読み書きもSystem.Runtime.InteropServices.Marshalクラスにメソッドがあります。 GCの管理外のメモリを扱うことになるのでメモリリークには注意が必要です。 | ||||||||
|
投稿日時: 2005-06-24 16:19
皆さんアドバイスありがとうございました。
アドバイスを参考にいろいろ調べて何とか解決しました。 アンマネージとマネージドの連携ということで難しく考えすぎていたようです。 要はCでのポインタの扱いを理解できていれば難しいことではなかったのですが、 最近はそのCでさえもご無沙汰していましたので戸惑ってしまいました。 ただし、GCについてはやはり注意が必要ですね。この辺は甕星さんのご指摘が 参考になりました。 ちなみに [MarshalAs(UnmanagedType.LPArry, SizeConst = 2000)} byte[] buff; とすると配列中に2000バイト確保してしまうので本件の構造体では適用できません。 ここでは ntPtr buff; として、System.Runtime.InteropServices.Marshal.AllocHGobalでメモリを確保する のが順当なようです。 |
1