COM與.NET的互操作(初級)
來源:互聯網
上載者:User
COM與.NET的互操作(初級)
COM與.NET的互操作中從.NET調用COM組件,如果使用VS.NET將變得非常容易,你只需要在你的工程中,添加對應的COM引用,編譯工具就在後台悄悄的把COM“變成”了.NET程式集。而從傳統的語言調用調用.NET組件卻不如那麼方便了。所以,我整理了個人調試成功的幾段程式希望對大家有一些協助,好了廢話少說進入正題。
一,從vbscript等指令碼調用.net組件
首先我們可以寫一個.NET dll如下
//the first file:netServer.cs
using System;
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyKeyFile("key.snk")]
namespace CSharpServer
{
//預設的是ClassInterfaceType.AutoDispatch,該方式下只產生dispatch介面
//只能被使用script、VB等late binding方式的COM客戶使用
[ClassInterfaceAttribute(ClassInterfaceType.AutoDual)]
public class SharpObject
{
private string m_strName;
public SharpObject(){}
public string Name //Property: Name, Get/Set
{
get { return m_strName; }
set { m_strName = value; }
}
}
}
//the second file: test.vbs
Dim obj
Set obj = CreateObject("CSharpServer.SharpObject")
obj.Name = "Chang Ming"
MsgBox "My Name is " & obj.Name
對這兩個檔案按如下方式編譯,為了清晰起見我們使用命令列工具(命令列工具環境可以從開始——>Microsoft Visual Studio .NET——>Visual Studio .NET 工具——>Visual Studio .NET 命令提示中進入)
1,產生密鑰檔案,用於給程式集強式名稱簽名
sn -k key.snk
2,使用強式名稱簽名,編譯成類庫,
csc /t:library netserver.cs
3,組建類型庫
tlbexp netserver.dll /out:netserver.tlb
4,註冊dll
regasm netserver.dll
5,移入gac全域組件快取
gacutil -i netserver.dll
6,調用測試指令碼
wscript test.vbs
在這裡有幾個需要注意的地方,1,必須要給程式集簽名,讓它具有強式名稱。2,必須將使用regasm註冊程式集,它將會在註冊表中添加相應的項。3,必須將簽名後的強式名稱程式集移入全域組件快取(gac)。4,必須要先安裝scriptengine了,微軟的指令碼執行引擎。這是從指令碼調用.net 程式集了,呵呵,很簡單吧?J
二,從C/C++調用.NET組件
還是一段程式,呵呵,程式就是我的生命:)
//file1 name:netServer.cs
using System;
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyKeyFile("key.snk")]
namespace CSharpServer
{
public interface IObject //聲明介面
{
double Sub(double c,double d);
}
//[ClassInterfaceAttribute(ClassInterfaceType.AutoDual)]
public class SharpObject:IObject
{
private string m_strName;
public SharpObject(){}
public string Name //Property: Name, Get/Set
{
get { return m_strName; }
set { m_strName = value; }
}
public double Add(double a,double b)
{
Console.WriteLine("the answer is {0}",a+b);
return a+b;
}
public double Sub(double c,double d) //實現介面方法
{
Console.WriteLine("the answer is {0}",c-d);
return c-d;
}
}
}
//file2 name: comclient.cpp
#include <windows.h>
#include <stdio.h>
#include <iostream.h>
#pragma warning (disable: 4278)
#import "netServer.tlb" no_namespace named_guids
int main(int argc, char* argv[])
{
IObject *cpi = NULL;
int retval = 1;
// Initialize COM and create an instance of the InterfaceImplementation class:
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(CLSID_SharpObject,
NULL,
CLSCTX_INPROC_SERVER,
IID_IObject,
reinterpret_cast<void**>(&cpi));
if (FAILED(hr))
{
printf("Couldn't create the instance!... 0x%x\n", hr);
}
else
{
printf("Calling function.\n");
retval = 0;
cout<<"10-4="<<cpi->Sub(10,4)<<endl;
printf("Returned from function.\n");
cpi->Release();//釋放com對象
}
// Be a good citizen and clean up COM:
CoUninitialize();
return retval;
}
編譯方法還是如前
1,產生密鑰檔案,用於給程式集強式名稱簽名
sn -k key.snk
2,使用強式名稱簽名,編譯成類庫,
csc /t:library netserver.cs
3,組建類型庫 //這一步很重要
tlbexp netserver.dll /out:netserver.tlb
4,註冊dll
regasm netserver.dll
5,移入gac全域組件快取
gacutil -i netserver.dll
6,編譯測試程式
cl COMClient.cpp
7,執行comclient.exe
說明:
在c/c++中調用com要麻煩一些,首先要調用COM庫函數CoInitialize(NULL);進行初始化,然後調用HRESULT hr = CoCreateInstance(CLSID_SharpObject,
NULL,
CLSCTX_INPROC_SERVER,
IID_IObject,
reinterpret_cast<void**>(&cpi));
其中CLSID_SharpObject是SharpObject類(com類)的類ID它是由工具產生的用來唯一標識SharpObject類,IID_IObject唯一標識IObject介面,如果CoCreateInstance成功的建立了COM對象,那麼FAILED(hr)將為false,得到com對象的指標後,就可以用它調用com對象中的方法了.