アンマネージからマネージへの構造体のマーシャリングについてMSDNを読みましたが解決
できなかったので教えてください。
現在、共通言語ランタイムの設定を使用するにしてアンマネージコードの中でマネージコ
ードを定義しています。
C++アンマネージ側
typedef struct
{
Long a;
short b;
short c;
Byte bt[8]
}DATA;
CreateData(DATA* data)
{
data->a = 1;
data->b = 2;
data->c = 3;
sprintf_s((char*)data->bt, 8, test);
SendData(data); →この関数の実態はマネージコードに定義
}
-----------------------------------------------------------------------------
C++/CLI マネージ側
[StructLayout(LayoutKind::Sequential, Pack=4, CharSet=Ansi)]
public value struct mDATA
{
int a;
int b;
int c;
[MarshalAs(UnmanagedType::ByValArray, SizeConst=8]
array<Byte>^ bt;
}
SendData(mDATA^ mdata);
{
// アンマネージから受け取った構造体の処理
}
アンマネージ側でDATA構造体を定義してCreateDataで構造体の中身をセットしその中の
SendData関数の引数で構造体をマネージ側へ渡そうとしています。マネージ側でもmDATA
構造体を定義してSendDataでアンマネージの構造体を受け取りたいのですが下記のエラー
となります
エラー内容:
error C2664: 'SendData' : 1番目の引数を'DATA*'から'mDATA^'に変換できません。使用
可能なユーザ定義された変換演算子がない、またはアンマネージ型をマネージ型に変換で
きません。
上記のようにアンマネージ構造体をマネージ構造体に渡すにはどうしたらよいでしょう
か?
MSDNでは
http://msdn.microsoft.com/ja-jp/library/ms384329(VS.71).aspx
を参考にしましたが何分、経験が浅いため理解に苦しみます。
>上記のようにアンマネージ構造体をマネージ構造体に渡すにはどうしたらよいでしょう
か?
単にマネージ構造体の変数を宣言して、アンマネージ構造体から
各メンバ変数をコピーするだけではだめなのですか?
ちなみに構造体を正しく定義していれば、Marshal::PtrToStructureでもいいと思いま
す。
>>subaruさん
アドバイスありがとうございます。休暇につき返信が遅くなりすみません。
>>単にマネージ構造体の変数を宣言して、アンマネージ構造体から
>>各メンバ変数をコピーするだけではだめなのですか?
おっしゃる通りの方法ではうまくいくのですが構造体そのものを渡せばすっ
きり処理が書けるかなと思いました。Marshal::PtrToStructureについては
これから調べてみます。
ただ
アンマネージ:
sprintf_s((char*)data->bt, 8, test);
マネージ:
[MarshalAs(UnmanagedType::ByValArray, SizeConst=8]
array<Byte>^ bt;
上記の型変換がうまくいかないようです・・・。
//アンマネージの配列
unsigned char aaa[2];
//マネージの配列
array<Byte>^ bbb[2]; = gcnew array<Byte>(2);
Marshal::Copy(static_cast<IntPtr>(aaa), bbb, 0, bbb->Length);
いろいろと調べて上記の方法でアンマネージの配列をマネージの配列にコピー
することが出来ました。
ただし以下のやりたいことがまだ実現できていません。
//アンマネージの構造体
typedef struct
{
long A;
short b;
short c;
byte d[8];
}uDATA
//マネージの構造体
[StructLayout(LayoutKind::Sequential, Pack=4, CharSet=CharSet::Ansi)]
public value struct mDATA
{
public:
int A;
int B;
int C;
[MarshalAs[UnmanagedType::ByValArray, SizeConst=8)]
array<Byte>^ D;
};
引数としてもらいた関数
void test(mDATA^ mdata);
Marshalクラスを使用してuDATAをtest関数の引数で定義しているmDATAで受け取りたいの
ですが行き詰っております。mDATAのメンバに1つずつコピーすることは出来るのですが
そもそも構造体をまるまるマーシャリングすることは可能なのでしょうか?
Marshal::PtrToStructureを調べてみて出来そうなことは書いてあるのですが具体的な実
装方法が分からないためお手数ですがアドバイスお願いします。
>引数としてもらいた関数
>void test(mDATA^ mdata);
value struct なのにハンドル渡し?
mDATA% の間違いではないですか?
>Marshalクラスを使用してuDATAをtest関数の引数で定義しているmDATAで受け取りたいの
>ですが行き詰っております。mDATAのメンバに1つずつコピーすることは出来るのですが
>そもそも構造体をまるまるマーシャリングすることは可能なのでしょうか?
そういうことができるかどうかは知りません。
調べてみたけど結局わかりませんでした。
>Marshal::PtrToStructureを調べてみて出来そうなことは書いてあるのですが具体的な実
>装方法が分からないためお手数ですがアドバイスお願いします。
アンマネージ側ののshort型の値とマネージ側のint型の値のサイズが違うので
対応が取れていません。そこさえ直せば、
SendData(static_cast<mDATA>(Marshal::PtrToStructure(IntPtr(data), mDATA::typeid)));
という感じで渡せると思います。
>>subaru さん
こんにちは
>>SendData(static_cast<mDATA>(Marshal::PtrToStructure(IntPtr(data),
mDATA::typeid)));
上記の「data」とは「mDATA」のメンバ変数のことでしょうか?
>上記の「data」とは「mDATA」のメンバ変数のことでしょうか?
いえ、DATA*型の変数です。
humanさんの最初の書き込みのCreateData関数内での呼び出し部分にあたります。
>>subaruさん
>>いえ、DATA*型の変数です。
>>humanさんの最初の書き込みのCreateData関数内での呼び出し部分にあたります。
ありがとうございます。渡す側の関数の引数は
SendData(static_cast<mDATA>(Marshal::PtrToStructure(IntPtr(data)
ですが関数の実態がある側の受け取る引数の定義も上記と同じにするのでしょうか?
素人ながらの質問で申し訳ございません。
受け側は、通常の値渡しであれば
void SendData(mDATA mdata)
{
}
でよいでしょう。
参照渡しなら
void SendData(mDATA% mdata)
出力引数なら
void SendData([System::Runtime::InteropServices::Out] mDATA% mdata)
となります。
ちなみに
void SendData(mDATA^ mdata)
としても value struct だと値渡しにしかならないようです。
>>subaruさん
関数の実態を
SendData(mDATA% data)
{
dataを受け取った処理・・・。
}
でdataに値が入っていることが確認出来ました。お手数おかけしました。
ただ型合わせにてアンマネージの
short
をマネージで
int16
これは問題ないのですが
マネージで
byte d[8];
アンマネージで
[MarshalAs[UnmanagedType::ByValArray, SizeConst=8)]
array<Byte>^ D;
とすると型変換に失敗します。マネージのbyte型はアンマネージだと上記の
表記では間違っているのでしょうか?
>>とすると型変換に失敗します。マネージのbyte型はアンマネージだと上記の
>>表記では間違っているのでしょうか?
失礼しました。アンマネージのbyte型です
int16、byte の定義が見つからないけど
System::Int16、unsigned char と同じ型であれば合ってると思います。
型変換に失敗するとは具体的にどのような状態になりますか?
>>subaruさん
エラーの内容は
error C2440:型キャスト:cli::array<Type>^からchar*に変換できません。
です。
最初の書き込みでCreateData内でByte bt[8]をsprintf_s((char*)data->bt, 8, test);
char型にキャストしているのでこれが原因かもしれません・・・。