Search code examples
c#c++c++-cliwrapper

Exposing C++ unmanaged code class pointers to C# with C++/CLI


Apologize for my very basic knowledge of C++/CLI, but it has only been introduced to me recently as a necessity. I am trying to create a wrapper for an unmanaged C++ library using C++/CLI. I have followed this helpful guide and can confirm that it (somehow) does the trick. The problem I have is with C++ pointers which expose access to public classes in the unmanaged library. In my CPP library I used them to call the methods from several classes, by having access to a single point-of-entry class. In C# I can't access the methods which should be accessible via these class pointers. I am getting an error stating "the member is inaccessible due to its protection level" and the "->" pointer does not grant access to the exposed class members.

Here's what my code looks like:

UnmanagedCode::ClassA

...
// some code
...
public:
    void doSomething() { ... };
    ClassB* classB() { return classB.get(); };
private:
    std::unique_ptr<ClassB> classB_ {};

C++/CLI wrapper

public ref class WrapperClass: public ManagedObject<UnmanagedCode::ClassA>
{
public:
    WrapperClass() : ManagedObject(new UnmanagedCode::ClassA) {}; // template class code in the hyperlink
    ~WrapperClass() {};
    void doSomething() { m_Instance->doSomething(); };
    UnmanagedCode::ClassB* classB() { return m_Instance->classB(); };
};

C# program

class Program
{
    static void Main(string[] args)
    {
        WrapperClass w = new WrapperClass();
        w.doSomething(); // this works fine
        w.classB(); // here is where I am getting the error
    }
}

Solution

  • My C# knowledge, is not quite as good as my C++, just as a note. I dont quite get what you are doing here:

    UnmanagedCode::ClassB* classB() { return m_Instance->classB(); };
    

    This line returns a pointer to a ClassB object, that you retrieve in C#. This would require the ClassB to also be a managed object, as far as i know, otherwise, i dont think you can call functions on the object, without creating delegates for unsafe function pointers.

    If i understand your issue correct, i think something like this, would fix your issue, in C++:

    void* classB() { return static_cast<void*>(m_Instance->classB()); };
    void doSomethingWithClassB(void* instance) {static_cast<ClassB*>(instance)->doSomethingWithClassB();}
    

    and then in C#:

        class Program
        {
            static void Main(string[] args)
            {
                WrapperClass w = new WrapperClass();
                w.doSomething();
                unsafe
                {
                    void* classb = w.classB();
                    w.doSomethingWithClassB(classb);
                }
            }