C++調用C#dll類庫中的方法(非顯性COM)


        一般在網上搜C++如何調用C#的函數,出來的結果都是做成COM組件,但是這種方法dll安裝麻煩,需要注冊COM組件,需要管理員權限,調試麻煩,經常需要重啟機器,反正有諸多不便。

        然后在看《CLR via C#》時看到一種方法,可以免去這種苦惱。少廢話,先上代碼。

C#類庫的:

namespace ClassLibrary1
{
    public class Class1
    {
        public static int pwzMethodName(String pwzArgument)
        {
            //Thread.Sleep(10000);
            Console.WriteLine(pwzArgument);
            Console.WriteLine(Thread.GetDomain().FriendlyName);
        }
    }
}

C++調用代碼:

#include <metahost.h>
#include <fstream>
using namespace std;

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

int _tmain(int argc, _TCHAR* argv[])
{
    ICLRMetaHost *pMetaHost = nullptr;
    ICLRMetaHostPolicy *pMetaHostPolicy = nullptr; 
    ICLRRuntimeHost *pRuntimeHost = nullptr; 
    ICLRRuntimeInfo *pRuntimeInfo = nullptr; 

    HRESULT hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost); 
    hr = pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo)); 

    if(FAILED(hr)) { 
        MessageBox(0,L"啟動出錯",L"Error",MB_OK|MB_ICONERROR);
        goto cleanup; 
    } 

    hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&pRuntimeHost)); 
    hr = pRuntimeHost->Start(); 

    DWORD dwRet = 0; 
    hr = pRuntimeHost->ExecuteInDefaultAppDomain(L"ClassLibrary1.dll", //不會產生新的進程
        L"ClassLibrary1.Class1", 
        L"pwzMethodName", 
        L"nimei", 
        &dwRet); 
    hr = pRuntimeHost->Stop(); 

cleanup: 
    if(pRuntimeInfo != nullptr) { 
        pRuntimeInfo->Release(); 
        pRuntimeInfo = nullptr; 
    } 

    if(pRuntimeHost != nullptr) { 
        pRuntimeHost->Release(); 
        pRuntimeHost = nullptr; 
    } 

    if(pMetaHost != nullptr) { 
        pMetaHost->Release(); 
        pMetaHost = nullptr; 
    } 
}

C#的代碼就不解釋了,就是提供一個int ClassLibrary1.Class1.pwzMethodName(String)的這樣一個方法。

重點看一下C++,它的思路就是通過metahost.h中的函數來操作clr環境。

第一句,CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost) 來初始化CLR環境,得到返回值pMetaHost。

第二句,pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo)) 來指定運行時,第一個參數.NET版本號,必須和你的C#dll的版本號兼容,而且 此參數必須與顯示在 C:\Windows\Microsoft.NET\Framework 或 C:\Windows\Microsoft.NET\Framework64 下的 .NET Framework 版本目錄名稱相匹配。比如,你的dll是用4.0編譯的,而你的Framework目錄有一下文件夾:v2.0.50727   v3.0   v3.5   v4.0.30319 ,所以這里的參數就是“v4.0.30319”,而且v是必須的。

第三句,pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&pRuntimeHost)) 將 CLR 加載到當前進程中,並返回運行時接口指針pRuntimeHost。

第四句,pRuntimeHost->Start() 將公共語言運行時 (CLR) 初始化到進程中。

第五句,pRuntimeHost->ExecuteInDefaultAppDomain

HRESULT ExecuteInDefaultAppDomain (
    [in] LPCWSTR pwzAssemblyPath,
    [in] LPCWSTR pwzTypeName, 
    [in] LPCWSTR pwzMethodName,
    [in] LPCWSTR pwzArgument,
    [out] DWORD *pReturnValue
);

pwzAssemblyPath是C#類庫的路徑和文件名,pwzTypeName是命名空間和類名,pwzMethodName是要調用的方法名稱,pwzArgument是要傳入的參數名稱,pReturnValue是函數返回值。

后面的都是釋放語句。

一般看來,這種方法只能調用int function(String para)這樣的函數,但是實際上LPCWSTR 是WCHAR *,既然是指針就可以傳遞對象,同樣返回值也可以是結構體或者數組。

本例地址:http://files.cnblogs.com/files/chihirosan/CPPCS%E4%BA%A4%E4%BA%92.rar


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM