Search code examples
c#c++pinvoke

Reverse PInvoke from native C++


I am currently trying to call a function from a C# DLL from an unmanaged C++ app.

After searching for hours on the web and SO, I found I have a few options.

I can use COM, DllExport, or use reverse PInvoke with delegates. The last sounded most appealing to me, so after searching SO I ended up here.

It states that the article shows how to use reverse PInvoke, but it looks like the C# code has to first import the C++ Dll, before it can be used.

I need to be able to use C++ to call my C# Dll functions, without running a C# app first.

Maybe reverse PInvoke isn't the way to do it, but I am quite inexperienced when it comes to low level stuff, so any pointers or tips on how to do this would be great.

The code in the link is

C#

using System.Runtime.InteropServices;

public class foo    
{    
    public delegate void callback(string str);

    public static void callee(string str)    
    {    
        System.Console.WriteLine("Managed: " +str);    
    }

    public static int Main()    
    {    
        caller("Hello World!", 10, new callback(foo.callee));    
        return 0;    
    }

    [DllImport("nat.dll",CallingConvention=CallingConvention.StdCall)]    
    public static extern void caller(string str, int count, callback call);    
}

C++

#include <stdio.h>    
#include <string.h>

typedef void (__stdcall *callback)(wchar_t * str);    
extern "C" __declspec(dllexport) void __stdcall caller(wchar_t * input, int count, callback call)    
{    
    for(int i = 0; i < count; i++)    
    {    
        call(input);    
    }    
}

Solution

  • Meh, just spin up your own CLR host and run what you need to:

    #include <mscoree.h>
    #include <stdio.h>
    #pragma comment(lib, "mscoree.lib") 
    
    void Bootstrap()
    {
        ICLRRuntimeHost *pHost = NULL;
        HRESULT hr = CorBindToRuntimeEx(L"v4.0.30319", L"wks", 0, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (PVOID*)&pHost);
        pHost->Start();
        printf("HRESULT:%x\n", hr);
    
        // target method MUST be static int method(string arg)
        DWORD dwRet = 0;
        hr = pHost->ExecuteInDefaultAppDomain(L"c:\\temp\\test.dll", L"Test.Hello", L"SayHello", L"Person!", &dwRet);
        printf("HRESULT:%x\n", hr);
    
        hr = pHost->Stop();
        printf("HRESULT:%x\n", hr);
    
        pHost->Release();
    }
    
    int main()
    {
        Bootstrap();
    }