對於某些跨平台程序,這也就意味着只能在windows下使用了
不過最近.Net開源或許以后可以跨平台
之前花了一些時間研究COM方式調用,太繁瑣不推薦。 COM方式調用總結
后來嘗試使用CLR C++,雖然可以用.Net的接口直接載入,但他只是一層C++的皮,最終沒能運用在實際項目中。
最后使用MS提供的CLR API接口,完成調用 MSDN CLR接口介紹
=======================================================
有幾個注意點:
1.官方一直強調的簽名格式static int pwzMethodName (String pwzArgument),並非某個C#特性,而是函數格式必須是帶一個string參數返回int型。否則在調用時會報找不到方法。
2.ExecuteInDefaultAppDomain中,dll路徑支持相對路徑格式,"xx.dll"是可以被識別的。
3.GetRuntime方法獲得的.Net版本號,需要去c:/windows/Microsoft.NET下找,64位對應Framework64,普通版對應Framework。如果目標機器沒有該文件夾,說明對應版本的.net未安裝。那么程序就會報錯。版本號第三位數字似乎是死的,應該都是統一的發行版。
4.在創建測試項目時,需要點掉預編譯頭選項,否則會出現許多莫名其妙的錯誤。
5.需要在管理員權限下使用
6.類可以是靜態類或者非靜態,但函數必須是靜態函數
參考代碼摘自github:
具體上代碼
C#

using System; using System.Collections.Generic; using System.IO; using System.Text; namespace ClassLibrary1 { public class Class1 { public static int EntryPoint(string arg) { File.AppendAllText("C:/xx.txt", "qweqwe"); return 0; } } }
C++

//Reference From GitHub entice:https://github.com/entice/client/blob/42f388d68b1954ef244c379560eeb4867ae80b7e/Loader/Loader/DllMain.cpp #include <Windows.h> #include <stdio.h> #include <iostream> #include <mscoree.h> #include <metahost.h> #include <assert.h> #pragma comment(lib, "mscoree.lib") #define BUFFER_SIZE 500 #include "stdafx.h" void StartTheDotNetRuntime(LPCWSTR runtimeVersion, LPCWSTR dllPath, LPCWSTR startClass, LPCWSTR startMethod, LPCWSTR startArgument) { ICLRMetaHost *pMetaHost = NULL; ICLRMetaHostPolicy *pMetaHostPolicy = NULL; ICLRDebugging *pCLRDebugging = NULL; CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost); CLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, (LPVOID*)&pMetaHostPolicy); CLRCreateInstance(CLSID_CLRDebugging, IID_ICLRDebugging, (LPVOID*)&pCLRDebugging); DWORD dwVersion = 0; DWORD dwImageVersion = 0; ICLRRuntimeInfo *pRuntimeInfo; HRESULT result; result = pMetaHost->GetRuntime(runtimeVersion, IID_ICLRRuntimeInfo, (LPVOID*)&pRuntimeInfo); assert(SUCCEEDED(result)); ICLRRuntimeHost * pRuntimeHost = NULL; result = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&pRuntimeHost); assert(SUCCEEDED(result)); result = pRuntimeHost->Start(); assert(SUCCEEDED(result)); DWORD dwRetCode = 0; result = pRuntimeHost->ExecuteInDefaultAppDomain(dllPath, startClass, startMethod, startArgument, &dwRetCode); assert(SUCCEEDED(result)); pRuntimeHost->Stop(); pRuntimeHost->Release(); pRuntimeInfo->Release(); pCLRDebugging->Release(); pMetaHostPolicy->Release(); pMetaHost->Release(); } void Loader() { wchar_t* runtimeVersionSpace = new wchar_t[BUFFER_SIZE]; wchar_t* dllPathSpace = new wchar_t[BUFFER_SIZE]; wchar_t* currentDir = new wchar_t[BUFFER_SIZE]; GetCurrentDirectoryW(BUFFER_SIZE, currentDir); StartTheDotNetRuntime(L"v4.0.30319", L"ClassLibrary1.dll", L"ClassLibrary1.Class1", L"EntryPoint", L""); free(runtimeVersionSpace); free(dllPathSpace); free(currentDir); } int _tmain(int argc, _TCHAR* argv[]) { HANDLE handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Loader, NULL, 0, NULL); for (size_t i = 0; i < 10; i++) { Sleep(100); } TerminateThread(handle, 0); return 0; }
然后把c#生成的dll,放到c++的build目錄下,再以管理員權限執行即可。
最后會在c盤根目錄下創建一個xx.txt文件。說明調用C#成功