- PR -

StructureToPtr関数について

1
投稿者投稿内容
しん
ベテラン
会議室デビュー日: 2008/05/27
投稿数: 63
投稿日時: 2008-11-13 22:22
言語:Visual Stadio C# 2008

共有メモリにsetするMarshal.StructureToPtr関数の処理で第1引数に
構造体配列渡しをしているのですが、
「指定された構造体は高速転送型かまたはレイアウト情報を含んでいな
ければなりません。」のエラーが発生するのですが、
構造体配列を渡すことは可能なのでしょうか?
知っている方がいらっしゃいましたらご教授願います。

SharedData[] data = new SharedData[2];
data[0].m_mylineNo = 'c';
data[0].m_url = 'd';
data[0].m_Value = 123;
data[0].m_mylineNo = 'a';
data[0].m_url = 's';
data[0].m_Value = 456;
⇒エラー箇所 System.Runtime.InteropServices.Marshal.StructureToPtr(data, m_memAreaPointer, false);
rain
ぬし
会議室デビュー日: 2006/10/19
投稿数: 549
投稿日時: 2008-11-14 00:40
前回までのあらすじ から、構造体そのもののコピーには成功したものとしてお話します。

構造体配列を渡すことは可能です。
細かいやりかたは忘れましたが、私の場合は 構造体のサイズ(Marshal.SizeOf()だっけか)×配列の要素数 ぶんのメモリを確保して、
0番目の要素をコピー → アドレスを構造体のサイズ分ずらす → 1番目の要素をコピー … と愚直にやっていた覚えがあります。

たぶんもっといい方法があると思うので、「構造体 配列 マーシャリング」あたりをキーワードに検索してみるとよいと思います。

↓当時の私が参考にしたサイトです。
http://www2u.biglobe.ne.jp/~kaduhiko/csharp_05.html
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-11-14 06:59
「レイアウト情報を含んでいなければなりません」って、書いてある通りだと思うのだけど?
どんな定義をしたのでしょう?
しん
ベテラン
会議室デビュー日: 2008/05/27
投稿数: 63
投稿日時: 2008-11-14 16:07
回答ありがとうございます。

下記のStructureToPtr関数で構造体配列(data)を第1引数に渡す場合、
どのように渡したらいいのでしょうか?
rainさんの回答で配列マーシャルで閲覧して定義等してみたのですが
同じエラーになります。
すみませんが、知っている方がいらっしゃいましたらご教授ください。

※ちなみに、配列ではなく構造体渡しでは、正常に共有メモリに登録されます。

構造体定義以下
public struct SharedData
{
public char m_mylineNo;
public char m_url;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string Message;
}

SharedData[] data = new SharedData[3];
data[0].m_mylineNo = 'c';
data[0].m_url = 'a';
data[0].Message = "123";

data[1].m_mylineNo = 'd';
data[1].m_url = 'b';
data[0].Message = "456";

data[2].m_mylineNo = 'e';
data[2].m_url = 'c';
data[0].Message = "789";

//// ↓↓↓↓↓↓↓↓↓構造体配列にした場合にエラーとなる
System.Runtime.InteropServices.Marshal.StructureToPtr             (data, m_memAreaPointer, false);


Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-11-14 17:44
「レイアウト情報を含んでいなければなりません」ですから、レイアウト情報を含ませればいいのではないでしょうか。
コード:
[StructLayout(LayoutKind.Sequential)]
public struct SharedData 
{ 
    public char m_mylineNo; 
    public char m_url; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 
    public string Message; 
}

しん
ベテラン
会議室デビュー日: 2008/05/27
投稿数: 63
投稿日時: 2008-11-14 18:28

「レイアウト情報を含んでいなければなりません」ですから、
レイアウト情報を含ませればいいのではないでしょうか。
コード:
-------------------------------------------------------------------------------
[StructLayout(LayoutKind.Sequential)]
public struct SharedData
{
public char m_mylineNo;
public char m_url;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string Message;
}
------------------------------------------------------------------------------
Jittaさん、ありがとうございます。

下記内容で付加してみたのですが、同じエラーになりました。
他に考えられる原因はあるんでしょうか?


[StructLayout(LayoutKind.Sequential)]
public struct SharedData
{
public char m_mylineNo;
public char m_url;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string Message;
}



ya
大ベテラン
会議室デビュー日: 2002/05/03
投稿数: 212
投稿日時: 2008-11-14 19:15
「レイアウト情報を含んでいなければなりません」と言われるのはおそらく渡された structure パラメータ(SharedData[] 型の変数)が SharedData 値型ではなく SharedData[] という参照型で値型ではないからですよ。

そのメソッドは名前の通り値型の変数を渡さなければ変換することができないのでしょう。

となると、配列をコピーしたいならば、普通に for で回しつつ、ポインタを進めつつ、一つずつ呼べばいいかと。
1

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