質問者
C++/CLIのMarshalに関する質問です。

質問
-
public ref struct Test { public: String ^str; int n; Test() { str = L"TEST"; n = 10; } }; int main(array<System::String ^> ^args) { Test^ test = gcnew Test(); int size = Marshal::SizeOf(test); IntPtr ptr = Marshal::AllocHGlobal(size); Marshal::StructureToPtr(test,ptr,true); }
上記のようなソースを実行するとエラーになります。C++ cli での ref class や ref struct をサイズオフするにはどうしたらよいのでしょうか。
どなたかご教示ください。
すべての返信
-
佐由理さんへ
自分はC言語,C++言語を学びC#へ移行したんですがC#でMarshal.SizeOfを使ったこと無かったです。
で、現在既存の作成したC++のdllをC++/CLIで、C#用のdllを作成しようとしています。
それで、ご質問のsizeofの結果の値はどうなってほしいかというより、sizeofする必要があったのでどうやったらよいか
がわからなかっただけなんです。もちろんC/C++なら結果はパディングされた結果が返ってくるのは知ってましたが、
特に気にはしてませんでした。ですので、メモリレイアウトも気にはしてませんでした。
これで質問の答えになってるかはわかりませんが、返信さしていただきます。
-
特に気にはしてませんでした。ですので、メモリレイアウトも気にはしてませんでした。
これでは意味がないように思います。というのは現状、エラーは出なくなっていますが、文字列L"TEST"がマーシャリング結果に含まれていないはずです。(単にポインターだけが含まれる。)このような問題があるので、Azuleanさんのように単にエラーを抑止するコメントを避け、マーシャリングによってどのようにデータを格納したいのか意識してもらおうと先のコメントをしました。
で、現在既存の作成したC++のdllをC++/CLIで、C#用のdllを作成しようとしています。
この1文は何を言おうとしているのか読み取れませんでした。肝心なことを言われているはずですが…。
ちなみにC++/CLIで定義したref structはC#のclassとしてそのまま使用することができます。メソッド呼び出し等の引数に使ったりできます。ですのでそもそもマーシャリングを行う必要がなかったかもしれません。
逆に、C++で定義したstructはC#では扱えずマーシャリングが必要になります。というか、今回の例でref struct Testをマーシャリングしたい場合、C++/CLIに限っては通常のstructを定義し値を格納し、そのアドレスを取得すればマーシャリングは完了します。
こういった話もあるので、もう少し詳しく目的を説明していただいた方がいいかもしれません。
-
フォローありがとうございます。
確かに文字列の件、考慮していない状態でのコメントになっており、問題があります。ところで、せっかく C++/CLI なので、自分で型変換しても良さそうですが、StructureToPtr を使おうとしているのはなぜだったんでしょうか。
(StringToHGlobalUni/FreeHGlobal あたりを使って文字列もフォローしながらかなぁ)
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。