views:

275

answers:

2

What are the options when it comes to using a .NET dll from a win32 process? I need to basically use a C# dll from a Win32 process.

I have a possible solution right now that requires adding the C# dll to the GAC (using RegAsm.exe), then calling the C# dll via COM wrapped calls. However that solution is pretty heavy. It requires that the .NET dll be added to the GAC on all machines that are supposed to run this win32 process.

Would it be possible to do this without having to call 'RegAsm' prior to being able to use the C# dll?

+6  A: 

You can use registration-free COM with .NET COM components - see here.

Another option is to use C++/CLI as a bridge. People are mostly familiar with using it to wrap unmanaged APIs to expose to managed code, but it actually works both ways - it is possible to compile with /clr, and yet produce a .dll assembly with plain unmanaged exports, which can be called from unmanaged code as usual. Here's a very simple example that exposes System::String::ToUpper that way:

// compile with cl.exe /clr /LD wrapper.cpp ole32.lib

#include <windows.h>

__declspec(dllexport)
wchar_t* ToUpper(const wchar_t* wcs)
{
    System::String^ s = gcnew System::String(wcs);
    array<wchar_t>^ chars = s->ToUpper()->ToCharArray();

    size_t size = chars->Length * 2;
    wchar_t* dst = (wchar_t*)CoTaskMemAlloc(size + 2);
    pin_ptr<wchar_t> src = &chars[0];
    memcpy(dst, src, size);
    dst[chars->Length] = 0;
    return dst;
}

This will produce wrapper.dll - hybrid managed/unmanaged assembly - and an export library wrapper.lib. The latter can be used in a pure native application as follows:

// compile with cl.exe test.cpp ole32.lib wrapper.lib
// note, no /clr

#include <stdio.h>
#include <windows.h>

wchar_t* ToUpper(const wchar_t* wcs);

int main()
{
    wchar_t* s = ToUpper(L"foo");  
    wprintf(L"%s", s);
    CoTaskMemFree(s);
}

In practice it will load CLR runtime into the calling process (unless it's already loaded there) and dispatch from native code to managed code transparently - all the magic is done by C++/CLI compiler.

Pavel Minaev
This sounds very good, thank you very much. I'll explore this solution
Zoran Simic
+5  A: 

There are two options.

First, you can use Registration Free COM Interop.

Second, you could use the CLR Hosting APIs to directly host the CLR, and load the assembly. This works without COM.

Reed Copsey
CLR hosting APIs can be used indirectly by exploiting C++/CLI - see the update to my answer.
Pavel Minaev