Search code examples
c#winapivisual-c++pinvoke

How can i use a C# dll in a Win32 C++ project?


I am working on a solution, most of its core engine is developed as Win32 C++ (and is Platform independent and is also used on OS X), some time ago we needed to call C++ dll's of core engine from C# and I was able to Load main solution's DLL in C# (by the help of some threads here on SO). but now we have certain things implemented in Managed C# dll and need to use it in Win32 C++ project? (and just function definitions and dll are provided)


Solution

  • You can create a managed C++ interop DLL to act as a wrapper around the C# library.

    Most tutorials on managed C++ unfortunately only explain how to wrap unmanaged C++ for use in C#. But it can work the other way also.

    Define an abstract interface class in your native C++ code, then create a concrete subclass inside the managed C++ DLL. Call into your C# objects in the method implementations.

    Finally, export a factory function that will instantiate the implementation class and return a base-class pointer that your native code can use.

    Here's a quick example:

    First, define the class interface in your native DLL.

    interopclassbase.h

    class InteropClassBase
    {
    public:
        virtual void doStuff() = 0;
        virtual int getValue() = 0;
        virtual void getString(CString* outStr) = 0;
    };
    

    Now you need to create a C++/CLI DLL that will allow you to mix native and managed code in a single assembly. Add a new C++ project to your solution, and in the project configuration set the "Common Language Runtime Support" option to Mixed (/clr).

    Once you've added a reference to your C# library (which we'll call ManagedLibrary) we can implement the interop class:

    interopclass.cpp

    #include "interopclassbase.h"
    #include <vcclr.h>
    
    public class InteropClass : public InteropClassBase
    {
    protected:
        gcroot<ManagedLibrary::ManagedObject^> m_managedObject;
    
    public:
        InteropClass()
        {
            m_managedObject = gcnew ManagedLibrary::ManagedObject();
        }
    
        virtual void doStuff()
        {
            m_managedObject->doStuff();
        }
    
        virtual int getValue()
        {
            return m_managedObject->getValue();
        }
    
        virtual void getString(CString* pOutStr)
        {
            System::String^ managedString = m_managedObject->getString();
            CString nativeString(managedString); // overloaded CString constructor
            if (pOutStr) *pOutStr = nativeString;
        }
    };
    
    __declspec(dllexport) InteropClassBase* getImplementationPointer()
    {
       return new InteropClass();
    }
    

    Now you just need to load the interop DLL from your native project and call the exported function.