Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to call Managed .NET code from Unmanaged code

I'm trying to find the best performing method of calling into Managed .NET code from Unmanaged C++ code. I have found information on Hosting .NET within my C++ application and I'm able to create a pRuntimeHost and start it without a problem.

The ExecuteInDefaultAppDomain seems very limited since I really want to send it a few parameters and have it return a structure of information. The most obvious alternative is to use COM methods but the current C# code isn't really setup as interfaces with methods.

Either way I want to return integers, strings (char *)s, doubles and other core C++ types. There is too much code on both sides to convert the C++ to C# and using Managed C++ isn't an acceptable solution, since the other groups using this C++ code don't want to start using Managed code for performance reasons.

The goal is modify the existing C++ and C# code as little as possible but still use methods within the C# code at specific points within the C++ without majorly affecting the speed of the C++ code.

Based on code found on the Internet the startup and shutdown sequence to host .NET is:

#include "stdafx.h"
#include <metahost.h>

#pragma comment(lib, "mscoree.lib")

int _tmain(int argc, _TCHAR* argv[])
{
    ICLRMetaHost       *pMetaHost       = NULL;
    ICLRMetaHostPolicy *pMetaHostPolicy = NULL;
    ICLRDebugging      *pCLRDebugging   = NULL;

    HRESULT hr;
    hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost);
    hr = CLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, (LPVOID*)&pMetaHostPolicy);
    hr = CLRCreateInstance(CLSID_CLRDebugging, IID_ICLRDebugging, (LPVOID*)&pCLRDebugging);

    DWORD dwVersion = 0;
    DWORD dwImageVersion = 0;
    ICLRRuntimeInfo *pRuntimeInfo;
    hr = pMetaHost->GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID *)&pRuntimeInfo);

    ICLRRuntimeHost * pRuntimeHost = NULL;
    hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID *)&pRuntimeHost);

    hr = pRuntimeHost->Start();

    DWORD dwRetCode = 0;
    //hr = pRuntimeHost->ExecuteInDefaultAppDomain(argv[1], L"MyNamespace.MyClass", L"Message", L"Hello World!", &dwRetCode);

    // Stop the CLR runtime and shutdown cleanly.
    hr = pRuntimeHost->Stop();
    hr = pRuntimeHost->Release();
    hr = pRuntimeInfo->Release();
    hr = pCLRDebugging->Release();
    hr = pMetaHostPolicy->Release();
    hr = pMetaHost->Release();

    return 0;
}
like image 704
Andrew Stern Avatar asked Dec 06 '11 20:12

Andrew Stern


People also ask

Is .NET core managed or unmanaged code?

NET Framework is managed code. Managed code uses CLR which in turns looks after your applications by managing memory, handling security, allowing cross - language debugging, and so on. The code, which is developed outside . NET, Framework is known as unmanaged code.

What is managed code why it is preferred over the traditional unmanaged native code?

What is managed code? A code which is written to aimed to get the services of the managed runtime environment execution like CLR(Common Language Runtime) in . NET Framework is known as Managed Code. It always implemented by the managed runtime environment instead of directly executed by the operating system.

Can we use unmanaged code in C#?

Execution of Unmanaged CodeFor executing unmanaged code wrapper classes are used in C#. In C# the unmanaged code is directly executed by the operating system. Generally, the executable files of unmanaged or unsafe code are in the form of binary images which are loaded into the memory.

How is a managed code executed?

Managed code is a code whose execution is managed by Common Language Runtime. It gets the managed code and compiles it into machine code. After that, the code is executed.


2 Answers

Yes, I agree with John. You don't really want to create a new instance of the runtime and host it explicitely. First, the plumbing behind this is not well documented and could change in future versions. Second, C++/CLI was designed to do exactly this in most efficient and safe way.

  1. Write native C++ interfaces which represents the required .Net funcionality.

  2. Set up a dll with CLR support which implements the native interfaces using umanaged classes. Inside of their implementation you can create and access CLR types and store instance variables in gcroot<T> fields. Use the clr interop funcionality to marshal back and forth between managed/unmanaged code, google or bing for marshal_as.

  3. Provide an (unmanaged) factory function, which creates an instance of this component. This + the unmanaged c++ interface is the API your native code will see. Use the dll exactly the same way you'd use an unmanaged dll.

like image 139
Paul Michalik Avatar answered Oct 11 '22 05:10

Paul Michalik


If it is acceptable, the best solution may be to create a managed C++ dll that sits in-between. Managed C++ code is the best/most-efficient way to bridged managed and unmanaged code.

You really don't want to add COM into the mix. That will slow things down much more.

Also, are these "performance reasons" to avoid managed code actually quantified? It sounds kind of like an anecdote thrown out to avoid something they just don't want. Also, you could point out that they are already using managed code, since C# is in the mix.

like image 38
John Fisher Avatar answered Oct 11 '22 05:10

John Fisher