views:

2442

answers:

3

I've built a DLL in C#. Now I want to use the R Environment to call functions in that DLL. The R environment supports calling unmanaged C/C++ DLL's but not into .NET DLL's. So my question is, can I call functions in a C# DLL from a C/C++ DLL? If so, do you have a link to info about how to do this?

+5  A: 

The most straight forward way of doing this is to expose one of the C# classes in your C# DLL as a COM object, and then create an instance of it from your C/C++ DLL. If that isn't an acceptable option, you'd need to create a mixed-mode C++ DLL (which contains both managed and unmanaged code). Your C/C++ DLL can call exported functions in your mixed-mode DLL, which can in turn forward the calls on to your C# class.

Andy
That mixed mode C++ DLL sounds like it would do the trick - I've just had a look at the templates available to create a mixed mode DLL project using VS2008 but don't see one. How would you go about starting off a mixed mode DLL?
Guy
If you create a new C++ Class Library, that creates a C++ .NET DLL project. As long as the "Common Language Runtime support" setting is set to "Common Language Runtime support (/clr)", you are free to use both managed and unmanaged code in the project.
Andy
+3  A: 

This article might help you out:

CLR Hosting APIs (MSDN)

Updated: There's a tool called mergebin that ships with the .NET SQLite wrapper you can use to create a mixed mode native/managed DLL. Grab the source code from:

SQLite for ADO.NET 2.0 (SourceForge)

You'll find the exe in the bin\tools folder.

Kev

Kev
Thanks for the link Kev - interesting reading.
Guy
+2  A: 

i know how to make C# accessible from C++, but I always start with C# and then wire it up, and then use my c++ to call C# functions, so that's not exactly what you want. I've posted the code here anyway...

C#

//function i want to call 
public static void GuiDelegate(string message)
{
    WriteToWPFGui(message); 
}

//notice i need to marshall my string from unmanaged <-> managed, my pinvoke sig
public delegate void CppCallback([MarshalAs(UnmanagedType.LPWStr)] string message);

public static void GuiWriter(CppCallback c) 
{
    GuiWriter(c);
}

//we need to access C++ 
[DllImport("C:\\projectName.dll", EntryPoint="CSharp_GuiWriter")] via a dll 
public static extern void GuiWriter(CppCallback jarg1);

//CppCallback is defined above
public static CppCallback gui_functor;

delegate void StringDelegate(string message);

//delegate assignment
StringDelegate gui_callback = GuiDelegate;
gui_functor = new CppCallback(gui_callback);

//this points to pinvoke sig -> pinvoke will step into 
projName.GuiWriter(gui_functor);

C++

typedef void (__stdcall *Callback)(PCWSTR); 
static Callback gui; 

//Assignment of the delegate to the function pointer
__declspec(dllexport) void __stdcall CSharp_GuiWriter(void * jarg1) 
{
    Callback arg1 = (Callback) 0 ;
    arg1 = (Callback)jarg1; 
    gui = arg1; 
}

//invocation
(*gui)(_T("make C# print this text"));
iterationx