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
1<windows.h>
2
3#include <stdio.h>
4
5#include <iostream.h>
6
7#pragma warning (disable: 4278)
8
9#import "netServer.tlb" no_namespace named_guids
10
11int main(int argc, char* argv[])
12
13{
14
15IObject *cpi = NULL;
16
17int retval = 1;
18
19// Initialize COM and create an instance of the InterfaceImplementation class:
20
21CoInitialize(NULL);
22
23HRESULT hr = CoCreateInstance(CLSID_SharpObject,
24
25NULL,
26
27CLSCTX_INPROC_SERVER,
28
29IID_IObject,
30
31reinterpret_cast<void**>(&cpi));
32
33if (FAILED(hr))
34
35{
36
37printf("Couldn't create the instance!... 0x%x\n", hr);
38
39}
40
41else
42
43{
44
45printf("Calling function.\n");
46
47retval = 0;
48
49cout<<"10-4="<<cpi->Sub(10,4)<<endl; cpi-="" from="" function.\n");="" printf("returned="">Release();// 释放 com 对象
50
51}
52
53// Be a good citizen and clean up COM:
54
55CoUninitialize();
56
57return retval;
58
59}
60
61编译方法还是如前
62
631, 生成密钥文件,用于给程序集强名称签名
64
65sn -k key.snk
66
672 ,使用强名称签名,编译成类库,
68
69csc /t:library netserver.cs
70
713 ,生成类型库 // 这一步很重要
72
73tlbexp netserver.dll /out:netserver.tlb
74
754 ,注册 dll
76
77regasm netserver.dll
78
795, 移入 gac 全局程序集缓存
80
81gacutil -i netserver.dll
82
836 ,编译测试程序
84
85cl COMClient.cpp
86
877 ,执行 comclient.exe
88
89说明:
90
91在 c/c++ 中调用 com 要麻烦一些,首先要调用 COM 库函数 CoInitialize(NULL); 进行初始化,然后调用 HRESULT hr = CoCreateInstance(CLSID_SharpObject,
92
93NULL,
94
95CLSCTX_INPROC_SERVER,
96
97IID_IObject,
98
99reinterpret_cast<void**>(&cpi));
100
101其中 CLSID_SharpObject 是 SharpObject 类( com 类)的类 ID 它是由工具生成的用来唯一标识 SharpObject 类, IID_IObject 唯一标识 IObject 接口,如果 CoCreateInstance 成功的创建了 COM 对象,那么 FAILED(hr) 将为 false, 得到 com 对象的指针后,就可以用它调用 com 对象中的方法了 .
102
103欢迎喜欢 COM 和 .NET 的兄弟姐妹和我讨论, MSN: [email protected]</void**></endl;></cpi-></void**></iostream.h></stdio.h></windows.h>