C# COM组件编写,并在C++上运行

前言

本篇文章使用的是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
23
using System;
using System.Runtime.InteropServices;

namespace ComTest
{
[ComVisible(true)]
[Guid("80EB95B3-62C5-4469-B897-81BFA9D33447")]
public interface ITestClass
{
[DispId(1)]
int Add(int x, int y);
}

[Guid("8FEBFADA-8442-4C50-A7FE-B788633EED8B")]
[ClassInterface(ClassInterfaceType.None)]
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
#include "stdafx.h"
#import ".\\ComTest.tlb" named_guids raw_interfaces_only

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;
}

文章目录
  1. 1. 前言
  2. 2. 新建并配置项目
  3. 3. 编写注意事项
|