VC++ 呼叫 C#生成DLL的兩種方法
今年在C++呼叫對方用C#寫的DLL時,遇到託管和非託管的問題。
原帖:
http://topic.csdn.net/u/20110916/12/fcf63501-45ef-46d9-92d1-6ffa91086a80.html
以及參考文章:
VisualC、Delphi或者VB等程式語言來編寫的DLL檔案,在編譯完成以後,產生DLL檔案已經是一個可以直接供計算機使用的二進位制檔案,而Visual C#生成的DLL不是獨立執行的程式,是某個程式的一個部分,只能由所屬的程式呼叫,使用者不能也不需要開啟它,Visual C#編譯器生成的託管程式碼雖然也是二進位制檔案,但不是可以直接供計算機使用的原始程式碼,實際上是一種中間語言(IL)程式碼,需要經過"下一代視窗服務"( Next Generation Windows Services,簡寫為NGWS ) runtime的即時編譯器(即JIT)進行編譯。用Visual C#生成的DLL檔案已經和以前的DLL檔案有了本質上的區別。用Visual C#生成的DLL檔案在程式設計中更多的表現為一種類(Class)或者類庫(Class Library)。
如果想在VC++的非託管程式碼中呼叫已經用VC#生成的託管的DLL,從兩個方向進行調整可以產生兩種辦法:(visual studio 2008)(下面方法都是對於同一平臺下,即C#跟VC++都是在windows平臺下)
一、對VC++的環境中進行修改使其支援託管程式碼:
vc++呼叫端增加公共語言執行時【clr】的支援以執行C#的程式:解決方案-》Properties(右鍵)-》Configuration Properties(展開左樹)->General(開啟子節點)->Common Language Runtime support(選中選項)->【Common Language Runtime support(/clr)】(選中)OK,現在就可以引入托管的動態連線庫來用了,不過在呼叫時還是得注意語法(new->gcnew,....),例如下:
- #include "stdafx.h"
- #using "SmartDeviceDLL.dll"
- using namespace SmartDeviceDLL;
- int _tmain(int argc, _TCHAR* argv[])
- {
- printf("1111111111111\n");
- SmartDeviceDLL::ICalculator ^pICalc=gcnew SmartDeviceDLL::Class1();
- long lResult =0;
- lResult=pICalc->Add(5,10);
- wprintf(L"the result is %d\n",lResult);
- printf("222222222222222222\n");
- char c;
- scanf("%c",&c);
- return 0;
- }
二、C#生成DLL端編譯成COM介面,供VC++以託管格式呼叫(命令的執行都是在visual studio command prompt (命令視窗)中)
1.新建一個C#的動態連線庫(在 模板 ,下單擊 類庫):- using System;
- using System.Linq;
- using System.Collections.Generic;
- using System.Text;
- namespace SmartDeviceDLL
- {
- public interface ICalculator
- {
- int Add(int Number1, int Number2);
- }
- public class Class1: ICalculator
- {
- public int Add(int Number1, int Number2)
- {
- return Number1 * Number2;
- }
- public static int TestMethod(String s)
- {
- Console.WriteLine("Managed assembly: [0]", s);
- return s.Length;
- }
- }
- }<span style="font-family: Arial, Verdana, sans-serif; white-space: normal; "> </span>
2.為程式集建立一個強命名的類庫,並在AssemblyInfo.cs檔案中用AssemblyKeyFile屬性指向它:
1)、使用強命名工具(Strong Name Utility)產生金鑰對:
sn -k MyKeyFile.snk
2)、在AssemblyInfo.cs檔案中用AssemblyKeyFile屬性指向它:
即在專案的檔案AssemblyInfo.cs中將[assembly: ComVisible(false)]用以下內容替換:
- [assembly: ComVisible(true)]
- [assembly: AssemblyDelaySign(false)]
- [assembly: AssemblyKeyFile("MyKeyFile.snk")] //指向剛生成的檔案(可用無漢字的絕對路徑)
3.把生成的庫檔案加入全域性程式集快取(Global Assembly Cache, .NET [Compact]Framework支援一個工具,通常位於:C\Wndows\Assembly下)以便可以從任何 COM 客戶端啟用它,可以使用工具GACUtil.exe,指定/i命令開關將一個程式集安裝到GAC中,同樣可以使用/u命令開關將一個程式集從GAC中解除安裝。注意:安裝的程式集必須是強命名程式集:
- GACUTIL /i SmartDeviceDLL.dll //可用SmartDeviceDLL.dll的絕對路徑,Wince平臺直接在命令視窗中用CGACUTIL(Compact)
4.用下面的命令為COM註冊剛才的程式集,生成COM庫檔案(程式集註冊工具讀取程式集中的後設資料,並將所需的項新增到登錄檔中,登錄檔允許 COM 客戶程式以透明方式建立 .NET Framework 類。類一經註冊,任何 COM 客戶程式都可以使用它,就好像該類是一個 COM 類。類僅在安裝程式集時註冊一次。程式集中的類例項直到被實際註冊時,才能從 COM 中建立)
- //下面命令註冊 SmartDeviceDLL.dll 中包含的所有公共類,並生成和註冊型別庫 SmartDeviceDLL.tlb,該型別庫包含 SmartDeviceDLL.dll 中定義的所有公共型別的定義
- REGASM SmartDeviceDLL.dll /tlb:SmartDeviceDLL.tlb
- //或者可以選中:解決方案->Properties(右鍵)->Build->【Register for COM interop】(Wince平臺的DLL此選項不可選)
5.建立非託管的VC++呼叫程式(此處用Win32 Console Project為例):
- #include "stdafx.h"
- #import "SmartDeviceDLL.tlb" named_guids raw_interfaces_only
- using namespace SmartDeviceDLL;
- int _tmain(int argc, _TCHAR* argv[])
- {
- printf("1111111111111\n");
- //初始化COM以及產生智慧指標
- HRESULT hr=CoInitializeEx(NULL,COINIT_MULTITHREADED);
- if(hr!=S_OK)
- printf("hr failed\n");
- else
- printf("hr ok\n");
- printf("222222222222222222\n");
- SmartDeviceDLL::ICalculatorPtr pICalc;
- printf("2.1\n");
- HRESULT hRes=pICalc.CreateInstance(__uuidof(Class1),NULL,CLSCTX_ALL);
- //HRESULT hRes=pICalc.CreateInstance(SmartDeviceDLL::CLSID_Class1);
- printf("2.2\n");
- if(hRes==S_OK)
- {
- printf("hRes ok\n");
- long lResult =0;
- pICalc->Add(5,10, &lResult);
- wprintf(L"the result is %d\n",lResult);
- }
- else
- printf("hRes failure\n");
- printf("333333333333\n");
- CoUninitialize();
- printf("4444444444444444444\n");
- char c;
- scanf("%c",&c);
- return 0;
- }
相關文章
- C# 生成DLL 並 呼叫C#
- C++呼叫 c#生成的dllC++C#
- C# 呼叫 C++ 生成的 dll 關鍵實現部分C#C++
- C#呼叫 C++的DLLC#C++
- LabVIEW生成.NET的DLL——C#下呼叫NI資料採集裝置功能的一種方法 [原創www.cnblogs.com/helesheng]ViewC#
- VS2012生成C的dll並呼叫以及Python呼叫C的DLLPython
- C# 生成隨機數,呼叫Random方法C#隨機random
- C++呼叫C#的動態庫dllC++C#
- python生成requirements.txt的兩種方法PythonUIREM
- php 呼叫dll 裡面的方法PHP
- 兩種方法使vue實現jQuery呼叫VuejQuery
- VS中呼叫DLL動態庫的方法
- C#呼叫python的方法C#Python
- c#呼叫C++DLL EntryPointNotFoundException 找不到入口點C#C++Exception
- 使用使用rundll32 呼叫指定dll的方法
- Laravel-ide-helper 生成模型註釋的兩種方法LaravelIDE模型
- C#呼叫js庫的方法C#JS
- c# 反射呼叫方法C#反射
- P/Invoke之C#呼叫動態連結庫DLLC#
- exe呼叫DLL的方式
- CefSharp ——js呼叫c#方法JSC#
- 如何建立Electron + Vue3專案, 並呼叫C# dllVueC#
- 亂序的兩種方法
- 關於C#委託三種呼叫的分享C#
- 探秘C#中的秘密通道:五種引人注目的方法呼叫內部或私有方法C#
- NX二次開發-C#使用DllImport呼叫libufun.dll裡的UF函式(反編譯.net.dll)呼叫loop等UF函式C#Import函式編譯OOP
- MATLAB 生成exe 的幾種方法Matlab
- C# 反射呼叫擴充類方法C#反射
- vue 跳轉的兩種方法Vue
- C#程式實現軟體開機自動啟動的兩種常用方法C#
- Win7系統電腦提示“libeay32.dll檔案丟失”的兩種解決方法Win7
- Nodejs如何呼叫Dll模組NodeJS
- C#配置程式引用的dll的位置C#
- C#拼接Json串的幾種方法C#JSON
- 兩種動態建立表格的方法
- python之建立類的兩種方法Python
- 【遊戲設計圖形學】在地圖上生成蜿蜒河流的兩種方法遊戲設計地圖
- c# 呼叫 C++ dll 傳入傳出型別對應說明(轉)C#C++型別
- Semantic Kernel/C#:接入智譜AI的兩種方式C#AI