2011-06-27 5 views
6

私はいくつかのC++コードを持っている:私は、C#から呼び出す必要がC++/CLIでC++インターフェイス(抽象クラ​​ス)をラップするにはどうすればよいですか?

namespace Compute { 
    class __declspec(dllexport) IProgressCB { 
    public:  
    virtual void progress(int percentCompleted) = 0; 
    };  
    double __declspec(dllexport) compute(IProgressCB *progressCB, ...); 
} 

を。
したがって、このC++コードをC++/CLIでラップしたいと思います。

私はcompute()関数をラップする方法を理解していますが、 IProgressインターフェイスをラップするにはどうすればよいですか?

(?C++クラスを継承するための.NETクラスのために可能ではないようだ)

答えて

2

このフレームワークは、取得する必要がありますあなたは既に始めました:

interface class IProgressEventSink 
{ ... }; 

class ProgressEventForwarder : IProgressEventCB 
{ 
    gcroot<IProgressEventSink^> m_sink; 
public: 
    ProgressEventForwarder(IProgressEventSink^ sink) : m_sink(sink) {} 

// IProgressEventCB implementation 
    virtual void OnProgress(ProgressInfo info) { m_sink->OnProgress(info.a, info.b); } 
}; 

ref class ComputeCLI 
{ 
    Compute* m_pimpl; 
// ... 

public: 
    RegisterHandler(IProgressEventSink^ sink) 
    { 
     // assumes Compute deletes the handler when done 
     // if not, keep this pointer and delete later to avoid memory leak 
     m_pimpl->RegisterHandler(new ProgressEventForwarder(sink)); 
    } 
}; 
+0

BTW。シンクとフォワーダーコードの構築を「自動化」する方法を知っていますか? – Andy

+0

@アンドレアス:「コードの構築」はあまり明確ではありません。 「コード生成」または「オブジェクト構築」を意味しますか? –

+0

申し訳ありません。私はコード生成を意味します。私はSWIGがC++/CLIの代わりにPInvokeコードを生成することを理解していますが、そのようなもの、おそらくより軽量なものが理想的でしょう。 – Andy

4

包まれたインスタンスへのポインタを保持するref classを使用します。

namespace ComputeCLI { 
    public ref class IProgressCB{ 
    public: 
     void progress(int percentCompleted) 
     { 
      // call corresponding function of the wrapped object 
      m_wrappedObject->progress(percentCompleted); 
     } 

    internal: 
     // Create the wrapper and assign the wrapped object 
     IProgressCB(Compute::IProgressCB* wrappedObject) 
      : m_wrappedObject(wrappedObject){} 

     // The wrapped object 
     Compute::IProgressCB* m_wrappedObject; 
    }; 

    public ref class StaticFunctions{ 
    public: 
     static double compute(IProgressCB^ progressCB, ...){ 
      Compute::compute(progressCB->m_wrappedObject, ...); 
     } 
    }; 
} 
+0

私はすでにC++/CLIから組み入れられるIProgressCBと呼ばれるC++クラスを持っています。このクラスは別のもの(IProgressCLIなど)と呼ばれる必要がありますか?また、compute()メソッドはC++ IProgressへのポインタを期待しているため、IProgressCLI must be IProgressCBを継承しますが、これは許可されていませんか? – Andy

+1

ラッパーコードを別の名前空間に入れることを検討する必要があります。 (おそらくComputeCli)したがって、同じ関数とクラス名を使うことができます。 compute関数は、管理対象インタフェースで動作する必要があります。私はこれを実証するためにコードを編集します。 – Stephan

+0

しかし、C++コードでC++/CLIインターフェイスを呼び出すように指示するにはどうすればよいですか?ここでの "フロー":C++ - > C++/CLI - > C#は通常とは逆です:C# - > C++/CLI-> C++。 – Andy

関連する問題