用一個(gè)完整的的小例子解說 C++調(diào)用C# com組件
? 我們知道C#開發(fā)效率是非常高的,特別是做一些漂亮的頁面就更適合用它了啊.如果你開發(fā)一個(gè)桌面應(yīng)用程序即想性能好點(diǎn)又想頁面漂亮點(diǎn)可以考慮用C++和C#一起用.反正現(xiàn)在Win7都集成NetFramework了,就不用糾結(jié)為了裝個(gè)C#的應(yīng)用程序而去再整個(gè)NetFramework裝上.可以用C#做成com組件,然后C++去調(diào)用.反過來也行.可以C++做成com,然后C#來調(diào)用.
下面我舉個(gè)簡單的小例子.我用的是VS 2008,操作系統(tǒng)是Win 7.
? 首先創(chuàng)建一個(gè)C# com組件.實(shí)現(xiàn)的功能很簡單,就是返回兩數(shù)相加的和.
?
1.新建一個(gè)C# Project,類型就選Class Library.取名ArwenAddCom
2.在項(xiàng)目中添加一個(gè)接口,取名IComTest.C++調(diào)用com組件中所有的功能只能通過接口來調(diào)用,不能直接調(diào)用類或函數(shù)
具體代碼:
using System.Runtime.InteropServices; //記得加這個(gè)命名空間
namespace ArwenAddCom
{
????[Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")]?// guid的產(chǎn)生可以通過vs自帶的工具.點(diǎn)菜單欄上的Tools ->Create GUID,然后選第4個(gè)選項(xiàng).Registry Format.
??????????//點(diǎn)按鈕New GUID,再點(diǎn)Copy.這樣你就可以把產(chǎn)生的guid復(fù)制下來,然后粘貼到這個(gè)地方來.當(dāng)然那個(gè)大括號得去掉.后面需要用到guid的地方也用這方式產(chǎn)生
??? [ComVisible(true)]
????public interface IComTest????????//記得用修飾符public
??? {
????????[DispId(1)]?????? //如果還要添加其他函數(shù)就繼續(xù)來個(gè)[DispId(2)],[DispId(3)]加在函數(shù)前面
????????int Plus(int one,?int two);
??? }
}
?
3.添加一個(gè)類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)].右擊項(xiàng)目名打開屬性窗口,點(diǎn)標(biāo)簽Build,選中Register for COMinterop.
?
如果不想把生成的dll共享,把它放到GAC中的程序集里.工作到此完成.點(diǎn)擊build,在bin目錄中會找到一個(gè)ArwenAddCom.dll文件.這個(gè)文件就是我們需要的com組件了.另外還會看到一個(gè)文件ArwenAddCom.tlb,正常情況應(yīng)該有的.如果萬一沒這個(gè)tlb文件也可以后面通過一些命令調(diào)用dll文件去生成它.反正C++調(diào)用時(shí)dll,tlb文件是不能少的.
如果想把dll放到GAC中則還要做第五步后再build
?
5.生成snk文件,并添加到項(xiàng)目中(可選的步驟)
?
先打開VS命令窗口,有點(diǎn)像用cmd打開的dos窗口.在開始簡單找到vs 2008,在visual studio tools下面有個(gè)Visual studio commandprompt.點(diǎn)擊打開它
默認(rèn)顯示c:windowssystem32.你可以先切換到其他窗口.比如輸入D:再回車就切換到D盤的路徑下了再輸入cd D:temp切換到temp目錄.cd加任何路徑就可以切換到d盤任何地方
然后輸入命令sn–k ArwenAddCom.snk?再回車,就會在temp目錄下生成一個(gè)snk文件.把ArwenAddCom.snk拷貝到項(xiàng)目的根目錄中.和csproj文件相同的目錄.
打開項(xiàng)目屬性窗口,點(diǎn)標(biāo)簽Signing,選中Sign the assembly.并在下面的下拉列表中點(diǎn)browse,然后彈出一個(gè)對話框來,選中ArwenAddCom.snk
再次點(diǎn)build生成dll文件.
?
C++調(diào)用 C# com組件
?
1.調(diào)用前要先把com組件注冊才行.
如果你剛調(diào)用dll和則build生成dll是在同一臺電腦上則不用注冊了.因?yàn)閎uild C#的工程時(shí)選了Register for COMinterop.就自動(dòng)給你注冊了
如果不在同一臺電腦上,那就要另外去注冊,要真正開發(fā)桌面開發(fā)程序人家拿個(gè)安裝程序去用時(shí)自然要重新注冊的.這種情況下肯定不能手動(dòng)注冊,是通過寫代碼. 這里為了簡單起見就只講下怎么手動(dòng)注冊
跟生成snk文件一樣要用到vs命令窗口.如果是沒有用到snk文件的dll注冊.先在vs命令窗口中把路徑切換到開始生成的dll所在的目錄.dll隨便放哪都一樣,只要找到那目錄就行.
如果是是使用了snk文件,則通過gacutil /i ArwenAddCom.dll 將dll放入GAC中
再通過REGASM ArwenAddCom.dll? /tlb:ArwenAddCom.tlb即可注冊dll并生成tlb文件.
補(bǔ)充:
如果已經(jīng)有tlb文件只注冊的話就是REGASM ArwenAddCom.dll,??????????? 如果是單獨(dú)想生成tlb文件是tlbexp /out:ArwenAddCom.tlb? ArwenAddCom.dll.
另外還可以通過REGASM /regfile:ArwenAddCom.reg ArwenAddCom.dll生成一個(gè)reg注冊腳本文件,你可以雙擊這個(gè)腳本文件去注冊.
?
2.注冊完了就可以在代碼中用了,先新建一個(gè)C++ project,類型選Win32 Console Application
project名字取UseCsharpCom,在向?qū)ы撁纥c(diǎn)finish.把ArwenAddCom.tlb文件拷貝到項(xiàng)目的任何目錄下.我就放在D:UseCsharpComUseCsharpCom.我們會看到一個(gè)UseCsharpCom.cpp文件,雙擊打開把默認(rèn)生成的代碼全部刪掉.敲入下面代碼:
#include "stdafx.h"
#include
#import "..UseCsharpComCsharpComTest.tlb" named_guids raw_interfaces_only
void _tmain(int argc, _TCHAR* argv[])
{
????CoInitialize(NULL);
?? CsharpComTest::IComTestPtr ptr;?????? //類似明志一個(gè)指向接口的指針
???ptr.CreateInstance(CsharpComTest::CLSID_ComTest);??? //實(shí)例化一個(gè)類
?? //這個(gè)地方有一點(diǎn)點(diǎn)奇怪我也還沒弄懂.在C#中的函數(shù)是int Plus(int,int).但類型在這里都轉(zhuǎn)成long了.另外就是我們不能直接
? //來個(gè)long a = ptr->Plus(1,2);這樣得不到a = 3,反正會出錯(cuò).這里函數(shù)Plus的參數(shù)變成三個(gè)了long Plus(long,long,long *).其中最后一個(gè)指針得兩數(shù)相加的結(jié)果
???long a = 1;
?? long * lPtr = &a;
??? ptr->Plus(1,2,lPtr);
??? std::cout<<a;
}
如果前面把dll放到GAC中,此時(shí)就可以正確運(yùn)行了.得到結(jié)果3
如果沒有把dll放到GAC中,則必須把dll文件拷貝到有UseCsharpCom.exe這個(gè)文件的目錄下.