2011-06-27 48 views
6

我有一些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包裝這個C++代碼。

我明白如何包裝compute()函數, 但我該如何包裝IProgress接口?

(現在看來,這是不可能的.NET類繼承C++類?)

回答

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。你知道我怎樣才能「自動化」Sink和Forwarder代碼的構造嗎? – Andy

+0

@Andreas:「構建代碼」不是很清楚。你的意思是「代碼生成」還是「對象構造」? –

+0

對不起。我的意思是代碼生成。據我所知,SWIG生成PInvoke代碼而不是C++/CLI,但類似的,也許更輕量級將是理想的。 – 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

我已經有一個名爲IProgressCB的C++類,它將包含在C++/CLI中;所以這個類必須被稱爲別的東西(例如IProgressCLI)?此外,compute()方法需要一個指向C++ IProgress的指針,所以IProgressCLI musth會繼承IProgressCB,但這似乎不被允許? – Andy

+1

你應該考慮把你的包裝代碼放到另一個名字空間中。 (也許ComputeCli)因此,你可以使用相同的功能和類名稱。計算功能必須與託管接口配合使用。我將編輯代碼來演示這一點。 – Stephan

+0

但是,如何告訴我的C++代碼調用C++/CLI接口?這裏的「流程」:C++ - > C++/CLI-> C#與通常情況相反:C# - > C++/CLI-> C++。 – Andy