VC6用C++调用VS中C#生成DLL/COM的方法和注意事项

先感慨一下,研究这个问题研究了四个工作日才解决,实在是太不容易了,现在很开心很得意,叉会腰哈哈~

虽然就是一件看起来很简单的事情,我相信你在看到我这篇文章之前也已经看过许多相关文章了,但是很多细节需要注意,哪一步没有做好可能就走入了一个无尽的陷阱绕许多弯路,把我的经验分享出来如果能帮助到也遇到相同问题的小伙伴,就真的太好不过了。(我的开发环境:WinXP-VC++6.0 C++ & Win7-VS2015 C#

用C++调用C#dll一般是两个方式

①C++直接调用C#生成的DLL。这个方法要求C++在编译时要选择公共运行时支持(CLR),因为我最终需要用VC6编译程序,我没在VC6中找到有关CLR的设置,又考虑到这个方法以后可能会存在很多平台的限制,就放弃了。

C++以COM形式调用C#生成的DLL。我用的是这个方法,下面具体来阐述一下。

首先,在C#方面的操作:

一、新建类库工程

上方选择.NET版本,建议选择2.0-4.0之间的,因为XP环境最高支持4.0,这个版本选择很重要,之后注册COM会有影响,要注意。

VC6用C++调用VS中C#生成DLL/COM的方法和注意事项_第1张图片

二、添加C#代码

在类文件里面编辑代码,写一个加法例子

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;//需要添加这个命名空间

namespace MyCom5
{
    [Guid("36A57710-4EA3-4EA1-9AA1-3EF1EB6209C4")]//菜单栏-工具-创建GUID-选5.[Guid(xxxx...)]后复制粘贴到此处

    public interface MyCom5_Interface
    {
        [DispId(1)]//说是每多一个方法就要写一个这个(1)、(2)...不写好像也没事
        int Add(int a, int b);
    }

    [Guid("90316C3B-6305-41D7-B5DB-28F62DDCC728"),InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    //Guid的生成同上,是不同的Guid哈,后面的一段代码是我copy来的,暂时不知道什么用处,似乎不加也没事的
    public interface MyCom5_Events

    {
        //C++调用方法需要走接口形式,这个方法接口虽然没写东西但是先写在这了吧,不知道啥用
    }
    [Guid("65498AC7-646B-445B-825F-309D308F04F6"),ClassInterface(ClassInterfaceType.None),ComSourceInterfaces(typeof(MyCom5_Events))]
    //同上
    public class Class1 : MyCom5_Interface
    {
        public int Add(int a, int b)
        {
            return a + b;
        }
    }
}

 三、配置及生成COM

代码写好以后需要做以下配置:

1)菜单-项目-属性-应用程序-程序集信息-使程序集COM可见(要勾选上),大概就是封装为一个COM并可见的意思

2)菜单-项目-属性-生成-为COM互操作注册(要勾选上),勾选这个就在本机注册了这个COM组件。

(说道注册,多说几句,以前一直不太懂注册组件是什么意思,我的理解是,COM组件不能够像有的DLL可以直接调用,需要告诉电脑COM组件的位置和一些数据信息,所以就需要将COM组件注册到注册表,这样当程序调用了这个COM组件的时候,系统就会自己去找到这个COM组件。一般用regsvr32在cmd中进行注册)

3)菜单-项目-属性-生成-目标平台改为x86,这个真的很重要啊,因为之后要用到XP中去

4)强名称密钥文件

封装为COM组件就需要给COM加密的意思,具体的操作是,首先运行VS的命令提示符,在开始菜单-Visual Studio 2015 -Visual Studio Tools - VS2015开发人员命令提示,和运行cmd是一样的界面,但是指令不一样一定要用这个哈。以管理员权限运行后,

输入 sn -k D:\MyCom5.snk

即可在D盘根目录生成强名称密钥文件,可以自己换路径和名字。再拷贝到C#工程和.csproj相同的目录下。

然后回到C#代码,打开AssemblyInfo.cs,在里面添加一句:

[assembly:AssemblyKeyFile("MyCom5.snk")]

5)生成类库文件

选择全部重新生成,就会在Debug下面生成三个文件分别是: .dll   .tlb   .pdb 最后一个没啥用,可以不管了

到此为止,C#的工作就完成了。

 

好了下面我们来到XP的VC6:

1)新建一个C++程序,选择一个控制台程序作为例子。

2)将之前在C#生成的.dll和.tlb文件拷贝到C++工程的和Debug文件相同目录下

3)编写代码

#include "stdafx.h"
#import "MyCom5.tlb"//添加调用tlb文件
using namespace MyCom5;//声明COM文件的命名空间

int main(int argc, char* argv[])
{
	CoInitialize(NULL);	//初始化函数
	MyCom5_InterfacePtr p(__uuidof(Class1));//定义一个智能指针
	int a = p->Add(4, 5);//使用COM中函数
	printf("%d\n",a);
	getchar();
	return 0;
}

这个时候编译的话是会报错的,因为我们还没有注册这个COM

4)注册COM

以往注册COM都是用指令regsvr32,但是C#写的COM需要在使用.NET中自带的Regsam.exe来注册,具体方法是:管理员权限打开cmd,先定位到Regasm.exe的目录,C:\Windows\Microsoft.NET\Framework\v2.0.50727,这个目录有两个要注意的地方,因为我是在XP中运行,并且.NET版本之前选的2.0,所以是Framework\v2.0.50727,如果是想要在64位机器上运行或者其他.NET版本生成的就要相应改一下,要不无法注册成功。输入regasm 路径\MyCom5.dll,注册成功会有提示信息。

好啦,一切就绪,激动人心的时刻要到了,先重新生成一下C++项目,编译链接运行。。。

什么??执行不了??运行错误??很头疼啊,为什么一切都是按照步骤好好做的,哪里出问题了呢。这个问题折磨了我好几天,最后发现是.dll文件不只是要拷贝到Debug同目录文件下,还要拷贝到和exe同目录下!疏忽了,后来听别人说是注册后的DLL文件是需要放在和exe同目录下的,不是说注册过后就可以不管它路径了,系统只会去和exe相同的路径下找。

好啦,最后终于成功了,开心心~~下班回家!

你可能感兴趣的:(VC6用C++调用VS中C#生成DLL/COM的方法和注意事项)