構造体のマーシャリングについて – プログラミング – Home

構造体のマーシャリングについて
 
通知
すべてクリア

[解決済] 構造体のマーシャリングについて

固定ページ 1 / 2

human
 human
(@human)
ゲスト
結合: 15年前
投稿: 26
Topic starter  

アンマネージからマネージへの構造体のマーシャリングについて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^'に変換できません。使用
可能なユーザ定義された変換演算子がない、またはアンマネージ型をマネージ型に変換で
きません。

上記のようにアンマネージ構造体をマネージ構造体に渡すにはどうしたらよいでしょう
か?


引用未解決
トピックタグ
human
 human
(@human)
ゲスト
結合: 15年前
投稿: 26
Topic starter  

MSDNでは
http://msdn.microsoft.com/ja-jp/library/ms384329(VS.71).aspx
を参考にしましたが何分、経験が浅いため理解に苦しみます。


返信引用
subaru
 subaru
(@subaru)
ゲスト
結合: 19年前
投稿: 381
 

>上記のようにアンマネージ構造体をマネージ構造体に渡すにはどうしたらよいでしょう
か?

単にマネージ構造体の変数を宣言して、アンマネージ構造体から
各メンバ変数をコピーするだけではだめなのですか?


返信引用
subaru
 subaru
(@subaru)
ゲスト
結合: 19年前
投稿: 381
 

ちなみに構造体を正しく定義していれば、Marshal::PtrToStructureでもいいと思いま
す。


返信引用
human
 human
(@human)
ゲスト
結合: 15年前
投稿: 26
Topic starter  

>>subaruさん

アドバイスありがとうございます。休暇につき返信が遅くなりすみません。

>>単にマネージ構造体の変数を宣言して、アンマネージ構造体から
>>各メンバ変数をコピーするだけではだめなのですか?

おっしゃる通りの方法ではうまくいくのですが構造体そのものを渡せばすっ
きり処理が書けるかなと思いました。Marshal::PtrToStructureについては
これから調べてみます。

ただ

アンマネージ:
sprintf_s((char*)data->bt, 8, test);

マネージ:
[MarshalAs(UnmanagedType::ByValArray, SizeConst=8]
array<Byte>^ bt;

上記の型変換がうまくいかないようです・・・。


返信引用
human
 human
(@human)
ゲスト
結合: 15年前
投稿: 26
Topic starter  

//アンマネージの配列
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を調べてみて出来そうなことは書いてあるのですが具体的な実
装方法が分からないためお手数ですがアドバイスお願いします。


返信引用
subaru
 subaru
(@subaru)
ゲスト
結合: 19年前
投稿: 381
 

>引数としてもらいた関数
>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)));

という感じで渡せると思います。


返信引用
human
 human
(@human)
ゲスト
結合: 15年前
投稿: 26
Topic starter  

>>subaru さん

こんにちは

>>SendData(static_cast<mDATA>(Marshal::PtrToStructure(IntPtr(data),
mDATA::typeid)));

上記の「data」とは「mDATA」のメンバ変数のことでしょうか?


返信引用
subaru
 subaru
(@subaru)
ゲスト
結合: 19年前
投稿: 381
 

>上記の「data」とは「mDATA」のメンバ変数のことでしょうか?

いえ、DATA*型の変数です。
humanさんの最初の書き込みのCreateData関数内での呼び出し部分にあたります。


返信引用
human
 human
(@human)
ゲスト
結合: 15年前
投稿: 26
Topic starter  

>>subaruさん

>>いえ、DATA*型の変数です。
>>humanさんの最初の書き込みのCreateData関数内での呼び出し部分にあたります。

ありがとうございます。渡す側の関数の引数は

SendData(static_cast<mDATA>(Marshal::PtrToStructure(IntPtr(data)

ですが関数の実態がある側の受け取る引数の定義も上記と同じにするのでしょうか?
素人ながらの質問で申し訳ございません。


返信引用
subaru
 subaru
(@subaru)
ゲスト
結合: 19年前
投稿: 381
 

受け側は、通常の値渡しであれば

void SendData(mDATA mdata)
{
}

でよいでしょう。

参照渡しなら
void SendData(mDATA% mdata)

出力引数なら
void SendData([System::Runtime::InteropServices::Out] mDATA% mdata)

となります。

ちなみに
void SendData(mDATA^ mdata)
としても value struct だと値渡しにしかならないようです。


返信引用
human
 human
(@human)
ゲスト
結合: 15年前
投稿: 26
Topic starter  

>>subaruさん

関数の実態を

SendData(mDATA% data)
{
dataを受け取った処理・・・。
}

でdataに値が入っていることが確認出来ました。お手数おかけしました。

ただ型合わせにてアンマネージの

short

をマネージで

int16

これは問題ないのですが

マネージで

byte d[8];

アンマネージで

[MarshalAs[UnmanagedType::ByValArray, SizeConst=8)]
array<Byte>^ D;

とすると型変換に失敗します。マネージのbyte型はアンマネージだと上記の
表記では間違っているのでしょうか?


返信引用
human
 human
(@human)
ゲスト
結合: 15年前
投稿: 26
Topic starter  

>>とすると型変換に失敗します。マネージのbyte型はアンマネージだと上記の
>>表記では間違っているのでしょうか?

失礼しました。アンマネージのbyte型です


返信引用
subaru
 subaru
(@subaru)
ゲスト
結合: 19年前
投稿: 381
 

int16、byte の定義が見つからないけど
System::Int16、unsigned char と同じ型であれば合ってると思います。

型変換に失敗するとは具体的にどのような状態になりますか?


返信引用
human
 human
(@human)
ゲスト
結合: 15年前
投稿: 26
Topic starter  

>>subaruさん

エラーの内容は

error C2440:型キャスト:cli::array<Type>^からchar*に変換できません。

です。

最初の書き込みでCreateData内でByte bt[8]をsprintf_s((char*)data->bt, 8, test);
char型にキャストしているのでこれが原因かもしれません・・・。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました