Tôi đang cố gắng tìm phương thức thực hiện tốt nhất để gọi vào mã Managed .NET từ mã C++ không được quản lý. Tôi đã tìm thấy thông tin về Hosting .NET trong ứng dụng C++ của tôi và tôi có thể tạo một pRuntimeHost và khởi động nó mà không gặp vấn đề gì.Cách tốt nhất để gọi mã Managed .NET từ mã không được quản lý
ExecuteInDefaultAppDomain có vẻ rất hạn chế vì tôi thực sự muốn gửi một vài tham số và trả về cấu trúc thông tin. Cách thay thế rõ ràng nhất là sử dụng các phương thức COM nhưng mã C# hiện tại không thực sự được thiết lập như các giao diện với các phương thức.
Dù bằng cách nào tôi muốn trả về số nguyên, chuỗi (char *) s, gấp đôi và các loại C++ lõi khác. Có quá nhiều mã trên cả hai mặt để chuyển đổi C++ thành C# và sử dụng Managed C++ không phải là giải pháp có thể chấp nhận được, vì các nhóm khác sử dụng mã C++ này không muốn bắt đầu sử dụng mã Quản lý vì lý do hiệu suất.
Mục đích là sửa đổi mã C++ và C# hiện tại càng ít càng tốt nhưng vẫn sử dụng các phương thức trong mã C# tại các điểm cụ thể trong C++ mà không ảnh hưởng lớn đến tốc độ của mã C++.
Dựa trên mã được tìm thấy trên Internet khởi động và tắt máy tự để lưu trữ NET là:
#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;
}
Lý do tạo một AppDomain bổ sung là mã C++ đã sử dụng AppDomain mặc định cho một số thứ và tôi không muốn có thêm .NET Assembly của mình can thiệp vào mã hiện tại và cũng để tránh làm cho công cụ của họ can thiệp vào . BTW Tôi quản lý để các lớp CLI làm việc hoàn hảo nhưng tôi vẫn đang cố gắng tìm ra cách để có được toàn bộ lớp CLI vào một AppDomain riêng biệt mà không phải là AppDomain mặc định. –
Chưa cố gắng thực hiện điều đó, nhưng về mặt lý thuyết, điều này không phải là vấn đề. Tôi hiểu kịch bản của bạn là để gọi vào một thành phần được quản lý từ một bản địa, phải không? Có một tính năng được gọi là "quảng bá chuỗi" (google hoặc bing) khiến cho một chuỗi gốc được quảng bá đến một chuỗi được quản lý, bất cứ khi nào nó cố gắng thực thi mã được quản lý lần đầu tiên. Kể từ khi CLR không có ý tưởng trong đó AppDomain mã được quản lý được gọi theo cách đó nên thực hiện, nó đặt nó vào mặc định. Vì vậy, bạn sẽ phải xử lý rõ ràng quá trình chuyển đổi đó, có thể bằng cách sử dụng họ 'msclr :: call_in_appdomain' của các hàm. –
Tôi đã ghi lại giải pháp cuối cùng của mình ở vị trí này: http://stackoverflow.com/questions/10301727/marshalling-c-pointer-interface-back-though-c-sharp-function-call-in-a-non-def –