6

Every example I can find is in C++, but I'm trying to keep my project in C. Is it even possible to host the CLR in a C program?

If so, can you point me to an example?

David Brown
  • 35,411
  • 11
  • 83
  • 132
  • 3
    CLR API is a COM API. Basically, you should be calling COM interfaces in C. – Mehrdad Afshari Aug 29 '09 at 02:10
  • ... and for doing so, you can find an article here: http://www.codeproject.com/KB/COM/com_in_c1.aspx – Mehrdad Afshari Aug 29 '09 at 02:14
  • I'm going to be honest and say that I have absolutely no idea what I'm doing. I'm a C# guy, not a C guy, so that article makes little sense to me. Is there a specific example of hosting the CLR, creating a .NET object instance, and executing a method on it (which I realize is probably fairly complicated)? – David Brown Aug 29 '09 at 02:22
  • In particular, you don't need the COM in Plain C article at all, hosting the CLR is much easier. It's nice *overview* article though. – arul Aug 29 '09 at 02:26

1 Answers1

10

As the above comments hint, there is a set of COM APIs for hosting the CLR, and you should be able to call these COM APIs from both C and C++.

As an example, below is a quick piece of (untested) C code that shows how to start up the CLR and execute a static method of a class in a managed assembly (which takes in a string as an argument and returns an integer). The key difference between this code and its C++ counterpart is the definition of COBJMACROS and the use of the <type>_<method> macros (e.g. ICLRRuntimeHost_Start) to call into the CLR-hosting COM interface. (Note that COBJMACROS must be defined prior to #include'ing mscoree.h to make sure these utility macros get defined.)

#include <windows.h>

#define COBJMACROS
#include <mscoree.h>

int main(int argc, char **argv)
{
    HRESULT status;
    ICLRRuntimeHost *Host;
    BOOL Started;
    DWORD Result;

    Host = NULL;
    Started = FALSE;

    status = CorBindToRuntimeEx(
                 NULL,
                 NULL,
                 0,
                 &CLSID_CLRRuntimeHost,
                 &IID_ICLRRuntimeHost,
                 (PVOID *)&Host
                 );
    if (FAILED(status)) {
        goto cleanup;
    }

    status = ICLRRuntimeHost_Start(Host);
    if (FAILED(status)) {
        goto cleanup;
    }

    Started = TRUE;

    status = ICLRRuntimeHost_ExecuteInDefaultAppDomain(
                 Host,
                 L"c:\\path\\to\\assembly.dll",
                 L"MyNamespace.MyClass",
                 L"MyMethod",
                 L"some string argument to MyMethod",
                 &Result
                 );
    if (FAILED(status)) {
        goto cleanup;
    }

    // inspect Result
    // ...

cleanup:
    if (Started) {
        ICLRRuntimeHost_Stop(Host);
    }

    if (Host != NULL) {
        ICLRRuntimeHost_Release(Host);
    }

    return SUCCEEDED(status) ? 0 : 1;
}

This sample should work with .NET 2.0+, although it looks like .NET 4.0 (not yet released) has deprecated some of these APIs in favor of a new set of APIs for hosting the CLR. (And if you need this to work with .NET 1.x, you need to use ICorRuntimeHost instead of ICLRRuntimeHost.)

reuben
  • 3,360
  • 23
  • 28
  • Any guess why this won't work: http://stackoverflow.com/questions/21537338/iclrruntimehost-executeindefaultappdomain-error-0x80131513 ? – Stefan Falk Feb 03 '14 at 20:45