0

I've a managed C# test DLL and I want to call its functions from my unmanaged C++ code.

The problem is that I can't find an example that shows how to call arbitrary functions from my c++ code, I could only get the ICLRRuntimeHost::ExecuteInDefaultAppDomain working, but this function does use a predefined method signature.

Question

I'm able to execuete the ShowMsg function from my C# DLL but I can't find out how to call methods with other signatures than int(int). Can someone please help me with that?

C++ Code

// interface definitions of functions from c# dll
typedef int (*TestCallbackPtr)(std::wstring info, int value1, double value2);
typedef int (*TestFunctionPtr)(std::wstring string1, int int1, double double1, TestCallbackPtr callback);

// path of my c# dll
auto pathDll = L"..." 

void RunTest()
{
    ICLRMetaHost* clrMetaHost = NULL;
    ICLRRuntimeInfo* clrRuntimeInfo = NULL;
    ICLRRuntimeHost* clrRuntimeHost = NULL;
    
    // loading the data above is excluded for simplicity!
    // ... 
    
    // -------------
    // Test 1: run ShowMsg => WORKING
    // -------------
    
    DWORD pReturnValue;
    HRESULT result = clrRuntimeHost->ExecuteInDefaultAppDomain(pathDll, L"Test.Managed", L"ShowMsg", L"Hello from C++", &pReturnValue);
    
    // -------------
    // Test 2: run TestFunction
    // -------------
    
    TestCallbackPtr callback = [](std::wstring info, int value1, double value2) {
        return 21;
    };
    TestFunctionPtr function = NULL;
    
    // how to continue? how can I execute the function here and assign my local function pointer so that following will work:
    // (*function)(L"Test", 45, 1.23, callback);
}

C# Code

namespace Test
{    
    public class Managed
    {
        public static int ShowMsg(string msg)
        {
            MessageBox.Show(msg);
            return 0;
        }

        public delegate int TestCallback([MarshalAs(UnmanagedType.LPWStr)] string info, int value1, double value2);

        public static int TestFunction(
            [MarshalAs(UnmanagedType.LPWStr)] string string1, 
            int int1,
            double double1,
            TestCallback callback)
        {
            string info = $"string1 = {string1} | int1 = {int1} | double1 = {double1}";
            int returnValue = callback(info, 5, 10.34);
            return returnValue;
        }
    }   
}
prom85
  • 16,896
  • 17
  • 122
  • 242
  • What's the difference between `ShowMsg` and `TestCallback`/`TestFunction`? `ShowMsg` has no explicit marshalling information. Isn't `LPWStr` mapping to `wchar_t*`? Have you tried `BStr` instead (or dropping the attribute entirely)? – Aconcagua May 27 '21 at 09:09
  • All sources I can find suggest creating a c++/cli dll that exports a native function. Do you have any reason to believe that using CLR host to call arbitrary functions is even possible? – JonasH May 27 '21 at 10:52
  • You have to use Reflection to find the method you want to MethodInfo.Invoke(). Works as well in native C++ as it does in C#, minus the code bloat. Get google hits with "clr _methodinfoptr", [this hit](https://learn.microsoft.com/en-us/answers/questions/215345/running-managed-executables-inside-an-unmanaged-ex.html) looks decent. – Hans Passant May 27 '21 at 12:08

0 Answers0