Sto cercando di trovare il metodo di chiamata più performante nel codice Managed .NET dal codice C++ non gestito. Ho trovato informazioni su Hosting .NET all'interno della mia applicazione C++ e sono in grado di creare un pRuntimeHost e avviarlo senza problemi.Il modo migliore per chiamare il codice Managed .NET dal codice Unmanaged
ExecuteInDefaultAppDomain sembra molto limitato poiché desidero davvero inviarlo alcuni parametri e restituire una struttura di informazioni. L'alternativa più ovvia è usare i metodi COM ma l'attuale codice C# non è realmente configurato come interfaccia con i metodi.
In entrambi i casi voglio restituire interi, stringhe (char *) s, doppi e altri tipi di C++ di base. C'è troppo codice su entrambi i lati per convertire il C++ in C# e l'utilizzo di Managed C++ non è una soluzione accettabile, dal momento che gli altri gruppi che utilizzano questo codice C++ non vogliono iniziare a utilizzare il codice gestito per motivi di prestazioni.
L'obiettivo è modificare il codice C++ e C# esistente il meno possibile, ma utilizzare ancora metodi all'interno del codice C# in punti specifici all'interno del C++ senza influire in modo significativo sulla velocità del codice C++.
Basato sul codice trovato su internet l'avvio e l'arresto di sequenza per ospitare NET è:
#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;
}
La ragione per la creazione di un ulteriore AppDomain è che il codice C++ utilizza già l'AppDomain predefinito per alcune cose e non voglio che i miei assembly .NET aggiuntivi interferiscano con il codice corrente e anche per evitare che la loro roba interferisca con il mio . BTW Sono riuscito a far funzionare perfettamente lo strato CLI, ma sto ancora cercando di capire come ottenere l'intero livello CLI in un AppDomain separato che non è l'AppDomain predefinito. –
Non ho ancora provato a farlo, ma teoricamente questo non dovrebbe essere un problema. Capisco il tuo scenario è quello di chiamare in un componente gestito da uno nativo, giusto? Esiste una funzionalità chiamata "promozione dei thread" (google o bing) che fa sì che un thread nativo venga promosso a uno gestito, ogni volta che tenta di eseguire il codice gestito. Poiché CLR non ha idea in quale appDomain debba essere eseguito il codice gestito chiamato in quel modo, lo inserisce in quello predefinito. Quindi dovrai gestire esplicitamente questa transizione, probabilmente usando la famiglia di funzioni 'msclr :: call_in_appdomain'. –
Ho documentato la mia soluzione finale in questa posizione: http://stackoverflow.com/questions/10301727/marshalling-c-pointer-interface-back-though-c-sharp-function-call-in-a-non-def –