none
C++/CLIのMarshalに関する質問です。 RRS feed

  • 質問

  • 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 をサイズオフするにはどうしたらよいのでしょうか。

    どなたかご教示ください。

    2011年6月29日 23:17

すべての返信

  • 何処でどんなエラーがでるか示してください。
    2011年6月30日 0:11
  • オフ(Off)ではなくオブ(Of)です。

    galacoさんの返信にもありますが、エラー内容が気になります。

    それに加えて

    • size変数の値はいくつになって欲しいか
    • マーシャリングによってどのようなメモリレイアウトで格納されて欲しいか
      (1byte目に何が入って2byte目に何が入って…size byte目に何が入るか)

    についてどうお考えですか?

    2011年6月30日 1:09
  • StructLayoutAttribute がついていないクラスを SizeOf に渡すと例外がでます。
    StructLayoutAttribute で Sequential などを指定してください。

    # ref struct は .NET 的にはクラス。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年6月30日 15:04
    モデレータ
  • 返信してくださった皆様ありがとうございました。

    Azuleanさんの言うとおりしたら例外がでませんでした。

    以下が変えたコードです。

    [StructLayout(LayoutKind::Sequential)]
    public ref struct Test
    {
    public:
    	String ^str;
    	int   n;
    	Test()
    	{
    		str = L"TEST";
    		n = 10;
    	}
    	
    	
    };
    

    まだどこかおかしなところがありましたら、教えてください。

    2011年6月30日 20:14
  • 私からの質問はどうなったのでしょうか…
    2011年6月30日 21:42
  • 佐由理さんへ

    自分はC言語,C++言語を学びC#へ移行したんですがC#でMarshal.SizeOfを使ったこと無かったです。

    で、現在既存の作成したC++のdllをC++/CLIで、C#用のdllを作成しようとしています。

    それで、ご質問のsizeofの結果の値はどうなってほしいかというより、sizeofする必要があったのでどうやったらよいか

    がわからなかっただけなんです。もちろんC/C++なら結果はパディングされた結果が返ってくるのは知ってましたが、

    特に気にはしてませんでした。ですので、メモリレイアウトも気にはしてませんでした。

     

    これで質問の答えになってるかはわかりませんが、返信さしていただきます。

    2011年7月1日 21:25
  • 特に気にはしてませんでした。ですので、メモリレイアウトも気にはしてませんでした。

    これでは意味がないように思います。というのは現状、エラーは出なくなっていますが、文字列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を定義し値を格納し、そのアドレスを取得すればマーシャリングは完了します。

    こういった話もあるので、もう少し詳しく目的を説明していただいた方がいいかもしれません。

    2011年7月1日 23:13
  • フォローありがとうございます。
    確かに文字列の件、考慮していない状態でのコメントになっており、問題があります。

    ところで、せっかく C++/CLI なので、自分で型変換しても良さそうですが、StructureToPtr を使おうとしているのはなぜだったんでしょうか。
    (StringToHGlobalUni/FreeHGlobal あたりを使って文字列もフォローしながらかなぁ)


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年7月2日 0:35
    モデレータ