10

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);    
    }    
}
Bali C
  • 30,582
  • 35
  • 123
  • 152

1 Answers1

11

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();
}
JerKimball
  • 16,584
  • 3
  • 43
  • 55
  • Thanks very much, I really appreciate the code example. The only problem is it can't find mscoree.h, and it isn't in my sdk path in program files, do you know where this header should be or where I can get it? Thanks again. – Bali C Jan 11 '13 at 11:32
  • @bali-c not 100% sure, but I think it's part of the framework sdk. You can grab it from msdn. – JerKimball Jan 11 '13 at 15:28
  • Thanks, I found it, but after copying all the files it was complaining about it came up with a whole load of errors in the headers. I'm using Code::Blocks, is that ok? Or should I be using VS? Thanks! – Bali C Jan 11 '13 at 15:47
  • @BaliC I'm not familiar enough with Code::Blocks to really say - I compiled this ok with VS, but I imagine there's some sort of guide online that would help. – JerKimball Jan 11 '13 at 16:10