前言
本篇文章使用的是VS2017,故以下内容操作均以VS2017版本为例子
部分代码在写本篇文章时与测试时所用代码略有不同,所以不保证能够生效
参考资料:
C++调用C# com组件:一个完整的的小例子
ClassInterface
新建并配置项目
新建一个Visual C#/类库(.NET FrameWork)
项目,此处以ComTest
作为项目名为例
在解决方案资源管理器中找到ComTest/Properties/AssemblyInfo.cs
,将内部的[assembly: ComVisible(false)]
由false改为true
打开项目 - 属性
,在生成 - 输出
中勾选”生成序列化程序集”
可选:勾选
签名 - 为程序集签名
然后选择强名称密钥文件(方面起见本人测试时使用的是新建的,未勾选”使用密码保护密钥文件”的)
编写注意事项
##1、C++调用com组件中所有的功能只能通过接口来调用
因此我们需要为暴露出来的类写一个public接口(通常接口名为”类名加上I前缀”)
该接口需要有属性[ComVisible(true)]
##3、需要为类和上述接口添加GUID.aspx)
GUI的生成可以在VS的工具 - 创建GUID
栏中生成,格式为[GUID(“xxxxxxx-xxxx … xxxx”)]
生产环境卸下,建议
##1、接口的方法有属性[DispId(X)]//X为不重复的整数
##2、类有属性[ClassInterface(ClassInterfaceType.None)]
代码例子如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23using System;
using System.Runtime.InteropServices;
namespace ComTest
{
[ ]
[ ]
public interface ITestClass
{
[ ]
int Add(int x, int y);
}
[ ]
[ ]
public class TestClass : ITestClass
{
public int Add(int x, int y)
{
return x + y;
}
}
}
#编译和注册COM组件
通过生成 - 生成ComTest
即可编译生成dll、tlb、pdb文件
由于VS在生成dll是会自动将代码注册至编译电脑,故COM组件的注册忽略,详情可见上方参考资料
#在C++中使用
将生成的dll、tlb、pdb全部导入C++项目中(导入后可能需要重新生成解决方案来更新引用,解决报错问题)
使用#import ".\ComTest.tlb" named_guids raw_interfaces_only
进行引用,引用路径取决于三个文件在项目文件夹中的位置
通过CoInitialize(NULL)
初始化COM组件
通过ComTest::ITestClassPtr ptr;
创建一个类的类似指针的东西,注意类型是”接口名+Ptr”
通过ptr.CreateInstance(ComTest::CLSID_TestClass)
实例化一个类
(也可以通过using namespace ComTest
省略前面的命名空间,此处的命名空间和COM组件在C#中定义的一致
通过ptr->Add(a,b,&c)
来调用类的方法,注意此处类型在C++中为long,而非C#中声明的int,且不是通过return返回值,而是在末尾将值赋值给一个指针
(不过为什么这样资料上似乎也不太清楚)
调用示例如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using namespace ComTest;
int main()
{
long a, b = 2, c = 3;
CoInitialize(NULL);
ITestClassPtr ptr;
ptr.CreateInstance(CLSID_TestClass);
ptr->Add(1, 2, &a);
printf_s("%ld", a);
return 0;
}