Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++/CLI Inheriting from a native C++ class with abstract methods and exposing it to C#

I've been googling around in circles trying to find an fully fledged example to this but to no avail.

I have a C++ API that presents a number of classes that contain pure virtual methods for the developer to extend from. What I'm attempting to do is provide this interface to C# via the C++/CLI.

I've managed to get the API compiled into the C++/CLI library and I've reached a sticking point as I'm new to this.

I'm aware that I need to create a wrapper to expose the C++/CLI unmanaged class to a managed .net class but I've not found a solid example or discussion that shows how to do this with the an abstract C++ class.

Can anyone point me in the right direction to a full example including C# test application that shows the end to end of how to create the wrapper for an abstract class. It appears to be a "Oh you just do X" thing but I can't find out what X is :). I've seen a few examples on here but they aren't very clear. It's been about 3 years since I tackled any C#.

Hope someone can help!

Sammich

like image 692
Shinigami Sandwich Avatar asked Apr 12 '13 22:04

Shinigami Sandwich


1 Answers

Using the code in the link posted by Hans Passant as a base, the following is what I think you are looking for. It won't compile like this because I have written this example 'inline' - put all the method implementations in the .cpp file and you should then be on the right track.

#pragma managed(push, off)
#include "oldskool.h"
#pragma comment(lib, "oldskool.lib")
#pragma managed(pop)

using namespace System;

ref class Wrapper; // You need a predeclaration to use this class in the
                   // constructor of OldSkoolRedirector.

// Overrides virtual method is native class and passes to wrapper class
class OldSkoolRedirector : public COldSkool {
public:
    OldSkoolRedirector(Wrapper ^owner) : m_owner(owner) { }
protected:
    virtual void sampleVirtualMethod() { // override your pure virtual method
        m_owner->callSampleVirtualMethod(); // body of method needs to be in .cpp file
    }
private:
    gcroot<Wrapper^> m_owner;
}

public ref class Wrapper abstract {
private:
    COldSkool* pUnmanaged;
public:
    Wrapper() { pUnmanaged = new OldSkoolRedirector(this); }
    ~Wrapper() { this->!Wrapper(); }
    !Wrapper() {
        if (pUnmanaged) {
            delete pUnmanaged;
            pUnmanaged = 0;
        }
    }
protected:
    virtual void sampleVirtualMethod() = 0; // Override this one in C#
internal:
    void callSampleVirtualMethod(){ 
        if (!pUnmanaged) throw gcnew ObjectDisposedException("Wrapper");
        sampleVirtualMethod(); 
    }
};
like image 66
mcdave Avatar answered Sep 20 '22 16:09

mcdave