2011-06-27 71 views
6

Tôi có một số mã C++:Làm cách nào để bọc giao diện C++ (lớp trừu tượng) trong C++/CLI?

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

mà tôi cần phải gọi từ C#.
Vì vậy, tôi muốn bọc mã C++ này trong C++/CLI.

Tôi hiểu cách quấn hàm tính toán(), nhưng làm cách nào để bọc giao diện IProgress?

(Có vẻ như nó không phải là có thể cho một lớp Net kế thừa một ++ lớp C?)

Trả lời

2

khuôn khổ này sẽ nhận được bạn đã bắt đầu:

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. Bạn có biết làm thế nào tôi có thể "tự động hóa" việc xây dựng các Sink và mã Forwarder? – Andy

+0

@Andreas: "xây dựng mã" không rõ ràng lắm. Bạn có nghĩa là "tạo mã" hoặc "xây dựng đối tượng" không? –

+0

Xin lỗi. Tôi có nghĩa là tạo mã. Tôi hiểu rằng SWIG tạo mã PInvoke thay vì C++/CLI, nhưng một cái gì đó như thế, có lẽ trọng lượng nhẹ hơn sẽ là lý tưởng. – Andy

4

Sử dụng một ref class nắm giữ một con trỏ đến dụ bọc:

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

Tôi đã có một lớp C++ được gọi là IProgressCB sẽ được đưa vào từ C++/CLI; vì vậy lớp này phải được gọi là cái gì khác (ví dụ: IProgressCLI)? Ngoài ra, phương thức compute() mong đợi một con trỏ tới một IProgress C++ để IProgressCLI phải thừa hưởng IProgressCB, nhưng điều này dường như không được cho phép? – Andy

+1

Bạn nên xem xét để đưa mã wrapper của bạn vào một không gian tên khác. (có thể là ComputeCli) Vì vậy, bạn có thể sử dụng cùng một hàm và tên lớp. Chức năng tính toán phải hoạt động với Giao diện được quản lý. Tôi sẽ chỉnh sửa mã để chứng minh điều này. – Stephan

+0

Nhưng làm thế nào để tôi nói mã C++ của mình để gọi giao diện C++/CLI? Các "dòng chảy" ở đây: C++ -> C++/CLI-> C# là đối diện của những gì thường xảy ra: C# -> C++/CLI-> C++. – Andy

Các vấn đề liên quan