- - PR -
C# Marshal.AllocHGlobal領域を構造体経由で読み書きしたい
1
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2005-01-17 23:43
Marshal.AllocHGlobal領域を構造体経由で読み書きする方法を知りたい。
マネージドコードからMarshal.AllocHGlobal領域を高速で読み書きしたい。 できればMarshal.AllocHGlobal領域を直接読み書きしたい。 現在は必要なデータをMarshal.Copyでbyte[]に毎回コピーしていますが、 容量が大きくなるとオーバーヘッドが大きくなるので最適なロジックではありません。 適切な方法を教えてください。 例えば構造体のアドレスをMarshal.AllocHGlobal領域に重ね合わせる等できるでしょうか?あるいは、もっとエレガントな方法があれば知りたい。 例 例えば構造体test1の先頭アドレスをmemPtrに移動できれば良いのでしょうか? using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Runtime.InteropServices; namespace WindowsApplication2 { /// <summary> /// Form1 の概要の説明です。 /// </summary> public class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.Button button1; /// <summary> /// 必要なデザイナ変数です。 /// </summary> private System.ComponentModel.Container components = null; public Form1() { // // Windows フォーム デザイナ サポートに必要です。 // InitializeComponent(); // // TODO: InitializeComponent 呼び出しの後に、コンストラクタ コードを追加してください。 // } /// <summary> /// 使用されているリソースに後処理を実行します。 /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows フォーム デザイナで生成されたコード /// <summary> /// デザイナ サポートに必要なメソッドです。このメソッドの内容を /// コード エディタで変更しないでください。 /// </summary> private void InitializeComponent() { this.button1 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // button1 // this.button1.Location = new System.Drawing.Point(40, 16); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(56, 48); this.button1.TabIndex = 0; this.button1.Text = "button1"; this.button1.Click += new System.EventHandler(this.button1_Click); // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 12); this.ClientSize = new System.Drawing.Size(292, 266); this.Controls.Add(this.button1); this.Name = "Form1"; this.Text = "Form1"; this.ResumeLayout(false); } #endregion /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> [STAThread] static void Main() { Application.Run(new Form1()); } private void button1_Click(object sender, System.EventArgs e) { // 配列要素数 int pSize = 1000; Test test1 = new Test(1000); // アンマネージなメモリ領域を確保する int memSize; unsafe { memSize = sizeof(double)+sizeof(int)*pSize+sizeof(bool); } IntPtr memPtr = Marshal.AllocHGlobal(memSize); // Test構造体経由で案マネージなメモリ領域を高速に読み書きしたい // 例えば構造体test1をアンマネージなメモリ領域に重ねあわせることはできるか // … } // テンプレーの構造体 [StructLayout(LayoutKind.Sequential)] public struct Test { public Test(int pSize) { a = 12.34; b = new int[pSize]; for(int i = 0;i < pSize;i++) { b[i] = i*10; } c = true; } public double a; public int[] b; public bool c; } } } | ||||
|
投稿日時: 2005-01-18 03:08
Marshal.Write***メソッドを使うのが一番早いと思います。
構造体のコピーはMarshal.StructureToPtrメソッドで可能です。 しかし配列を含む構造体の場合、通常は配列へのポインタだけを持つことになります。 メンバにMarshalAs属性をUnmanagedType.ByValArrayで指定する事で配列各要素をフラットに持つ事が可能ですが、 同時にSizeConstも指定しなくてはいけない=固定長配列限定になります。 なにより構造体を一々マーシャリングするためか、思ったほどの効率にはなりません。 そこで、構造体の各メンバをMarshal.Write***メソッドで書き込んでいく手法です。 これなら、そもそも構造体である必要のないデータなら構造体にする事もなく書き込む事もできます。 ひろしさんが提示された構造体を書き込む場合は次のようなコードになります。
しかしながら、それほど速度が絶対的に必要ならば、 その部分をC++などで書く方がいいのではないでしょうか。 | ||||
|
投稿日時: 2005-01-19 12:53
ご回答ありがとうございます。
ご指摘の回答で問題が解決しました。 | ||||
|
投稿日時: 2005-01-19 12:53
ご回答ありがとうございます。
ご指摘の回答で問題が解決しました。 |
1