2017-03-28 14 views
1

私は管理されていないC++ライブラリで作業するためにbrigdeクラスで作業しています。Marshallオブジェクトの属性がコンパイラエラーを生成します

ref class ManagedClass 
    { 
    private: 
     UnManagedClass* m_UnManaged; 
     String^ m_someString; 
    public: 
     UserAgent_Managed(String^ someString) 
     { 
      m_someString = someString; 

      // Compiler error 
      // Severity Code Description Project File Line Suppression State Error C2665 'msclr::interop::marshal_as': none of the 3 overloads could convert all the argument 
      // types  

      std::string unManagedString = msclr::interop::marshal_as<std::string>(m_someString); 

      // Following works 
      // std::string unManagedString = msclr::interop::marshal_as<std::string>(someString); 


      m_UnManaged = new UnManagedClass(unManagedString); 
     } 
    }; 

私はオブジェクト属性m_someStringstd::string unManagedString = msclr::interop::marshal_as<std::string>(m_someString);を呼び出すと、コンパイラは一致marshal_asメソッドのシグネチャが存在しないことを私に語った:私は、次の(減少)のサンプルコードに問題があることをしました。 someStringパラメータで同じことを実行すると、コンパイラはエラーをスローしません。私は何が欠けていますか? m_someStringsomeStringはいずれもString^です。

Thxを

答えて

2

marshal_as()機能は非常に友好的ではない、それはこのコードをコンパイルできるように過負荷が含まれていません。どのオーバーロードが利用可能であるかを示すIntelliSenseポップアップを見ることで問題を解決できます。

std::string marshal_as<std::string, System::String^>(System::String^ const & _from_obj) 

悪魔が&であり、管理されていない参照:使用しようとしている1第4回です。はい、マネージオブジェクト参照へのアンマネージ参照、心が吹き飛ばされました:)しかし、C++/CLIでは完全に合法ですが、実行時にこの引数はオブジェクト参照への生ポインタに変わります。

テンプレートがSystem::String^ % _from_objのオーバーロードを提供していれば、それはコンパイルされていました。それはしません。 %&の区別は、C++/CLIの多くの点で重要な意味を持ちます。%という管理の参照を宣言しています。ドキュメント内に「トラッキング参照」と呼ばれています。ガベージコレクタが認識しているもので、GCヒープを圧縮するときに更新できるもの。それ以外の場合は、管理されていない参照と意味的に完全に同じです。

GCが&の参照を更新できないことはここでハングアップしています。コンパイラは、pin_ptr <>以外のマネージ型のメンバへのアンマネージポインタの生成を禁じています。 marshal_as()関数が実行されている間でも、ガベージコレクタはいつでもキックすることができます。たとえば、オブジェクトを割り当てる別のスレッドによってトリガされます。 ManagedClassオブジェクトを移動し、オブジェクトへの生ポインタを無効にします。関数が実行時に古いポインタを使用し続けると、関数がガベージを生成し、GCヒープを破損する可能性があります。

someStringオブジェクト参照は、スタックまたはプロセッサレジスタに格納され、コレクションの発生時には変更できません。コンパイラからの苦情はありません。

ここでは適切な回避策がありますが、コンストラクタ引数は現状のまま良好です。しかし、通常は明示的に提供し、メンバ値をローカル変数に格納する必要があります。言い換えれば、次のような文章を書いてください。

auto temp = this->m_someString; // Intentional temporary 
    auto str = marshal_as<std::string>(temp); 
+0

試してみてください。速い答えのためのThx。 – Moerwald