C++呼叫C# com元件:一個完整的的小例子
我們知道C#開發效率是非常高的,特別是做一些漂亮的頁面就更適合用它了啊.如果你開發一個桌面應用程式即想效能好點又想頁面漂亮點可以考慮用C++和C#一起用.反正現在Win7都整合NetFramework了,就不用糾結為了裝個C#的應用程式而去再整個NetFramework裝上.可以用C#做成com元件,然後C++去呼叫.反過來也行.可以C++做成com,然後C#來呼叫.
下面我舉個簡單的小例子.我用的是VS 2008,作業系統是Win 7.
首先建立一個C# com元件.實現的功能很簡單,就是返回兩數相加的和.
1.新建一個C# Project,型別就選Class Library.取名ArwenAddCom
2.在專案中新增一個介面,取名IComTest.C++呼叫com元件中所有的功能只能通過介面來呼叫,不能直接呼叫類或函式
具體程式碼:
using System.Runtime.InteropServices; //記得加這個名稱空間
namespace ArwenAddCom
{
[Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的產生可以通過vs自帶的工具.點選單欄上的Tools ->Create GUID,然後選第4個選項.Registry Format.
//點按鈕New GUID,再點Copy.這樣你就可以把產生的guid複製下來,然後貼上到這個地方來.當然那個大括號得去掉.後面需要用到guid的地方也用這方式產生
[ComVisible(true)]
public interface IComTest //記得用修飾符public
{
[DispId(1)] //如果還要新增其他函式就繼續來個[DispId(2)],[DispId(3)]加在函式前面
int Plus(int one, int two);
}
}
3.新增一個類ComTest,繼承介面IComTest,具體程式碼
using System.Runtime.InteropServices;
namespace ArwenAddCom
{
[Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]
[ClassInterface(ClassInterfaceType.None)]
public class ComTest : IComTest
{
public int Plus(int a, int b)
{
return a + b ;
}
}
}
4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].右擊專案名開啟屬性視窗,點標籤Build,選中Register for COMinterop.
如果不想把生成的dll共享,把它放到GAC中的程式集裡.工作到此完成.點選build,在bin目錄中會找到一個ArwenAddCom.dll檔案.這個檔案就是我們需要的com元件了.另外還會看到一個檔案ArwenAddCom.tlb,正常情況應該有的.如果萬一沒這個tlb檔案也可以後面通過一些命令呼叫dll檔案去生成它.反正C++呼叫時dll,tlb檔案是不能少的.
如果想把dll放到GAC中則還要做第五步後再build
5.生成snk檔案,並新增到專案中(可選的步驟)
先開啟VS命令視窗,有點像用cmd開啟的dos視窗.在開始簡單找到vs 2008,在visual studio tools下面有個Visual studio commandprompt.點選開啟它
預設顯示c:\windows\system32.你可以先切換到其他視窗.比如輸入D:再回車就切換到D盤的路徑下了再輸入cd D:\temp切換到temp目錄.cd加任何路徑就可以切換到d盤任何地方
然後輸入命令sn–k ArwenAddCom.snk 再回車,就會在temp目錄下生成一個snk檔案.把ArwenAddCom.snk拷貝到專案的根目錄中.和csproj檔案相同的目錄.
開啟專案屬性視窗,點標籤Signing,選中Sign the assembly.並在下面的下拉列表中點browse,然後彈出一個對話方塊來,選中ArwenAddCom.snk
再次點build生成dll檔案.
C++呼叫 C# com元件
1.呼叫前要先把com元件註冊才行.
如果你剛呼叫dll和則build生成dll是在同一臺電腦上則不用註冊了.因為build C#的工程時選了Register for COMinterop.就自動給你註冊了
如果不在同一臺電腦上,那就要另外去註冊,要真正開發桌面開發程式人家拿個安裝程式去用時自然要重新註冊的.這種情況下肯定不能手動註冊,是通過寫程式碼. 這裡為了簡單起見就只講下怎麼手動註冊
跟生成snk檔案一樣要用到vs命令視窗.如果是沒有用到snk檔案的dll註冊.先在vs命令視窗中把路徑切換到開始生成的dll所在的目錄.dll隨便放哪都一樣,只要找到那目錄就行.
如果是是使用了snk檔案,則通過gacutil /i ArwenAddCom.dll 將dll放入GAC中
再通過REGASM ArwenAddCom.dll /tlb:ArwenAddCom.tlb即可註冊dll並生成tlb檔案.
補充:
如果已經有tlb檔案只註冊的話就是REGASM ArwenAddCom.dll, 如果是單獨想生成tlb檔案是tlbexp /out:ArwenAddCom.tlb ArwenAddCom.dll.
另外還可以通過REGASM /regfile:ArwenAddCom.reg ArwenAddCom.dll生成一個reg註冊指令碼檔案,你可以雙擊這個指令碼檔案去註冊.
2.註冊完了就可以在程式碼中用了,先新建一個C++ project,型別選Win32 Console Application
project名字取UseCsharpCom,在嚮導頁面點finish.把ArwenAddCom.tlb檔案拷貝到專案的任何目錄下.我就放在D:\UseCsharpCom\UseCsharpCom.我們會看到一個UseCsharpCom.cpp檔案,雙擊開啟把預設生成的程式碼全部刪掉.敲入下面程式碼:
#include "stdafx.h"
#include <iostream>
#import "..\UseCsharpCom\CsharpComTest.tlb" named_guids raw_interfaces_only
void _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
CsharpComTest::IComTestPtr ptr; //類似明志一個指向介面的指標
ptr.CreateInstance(CsharpComTest::CLSID_ComTest); //例項化一個類
//這個地方有一點點奇怪我也還沒弄懂.在C#中的函式是int Plus(int,int).但型別在這裡都轉成long了.另外就是我們不能直接
//來個long a = ptr->Plus(1,2);這樣得不到a = 3,反正會出錯.這裡函式Plus的引數變成三個了long Plus(long,long,long *).其中最後一個指標得兩數相加的結果
long a = 1;
long * lPtr = &a;
ptr->Plus(1,2,lPtr);
std::cout<<a;
}
如果前面把dll放到GAC中,此時就可以正確運行了.得到結果3
如果沒有把dll放到GAC中,則必須把dll檔案拷貝到有UseCsharpCom.exe這個檔案的目錄下.