用一个完整的的小例子解说 C++调用C# com组件
扫描二维码
随时随地手机看文章
我们知道C#开发效率是非常高的,特别是做一些漂亮的页面就更适合用它了啊.如果你开发一个桌面应用程序即想性能好点又想页面漂亮点可以考虑用C++和C#一起用.反正现在Win7都集成NetFramework了,就不用纠结为了装个C#的应用程序而去再整个NetFramework装上.可以用C#做成com组件,然后C++去调用.反过来也行.可以C++做成com,然后C#来调用.
下面我举个简单的小例子.我用的是VS 2008,操作系统是Win 7.
首先创建一个C# com组件.实现的功能很简单,就是返回两数相加的和.
1.新建一个C# Project,类型就选Class Library.取名ArwenAddCom
2.在项目中添加一个接口,取名IComTest.C++调用com组件中所有的功能只能通过接口来调用,不能直接调用类或函数
具体代码:
using System.Runtime.InteropServices; //记得加这个命名空间
namespace ArwenAddCom
{
[Guid("DA07B88D-29F0-41cf-B3D3-611010E6F3FF")] // guid的产生可以通过vs自带的工具.点菜单栏上的Tools ->Create GUID,然后选第4个选项.Registry Format.
//点按钮New GUID,再点Copy.这样你就可以把产生的guid复制下来,然后粘贴到这个地方来.当然那个大括号得去掉.后面需要用到guid的地方也用这方式产生
[ComVisible(true)]
public interface IComTest //记得用修饰符public
{
[DispId(1)] //如果还要添加其他函数就继续来个[DispId(2)],[DispId(3)]加在函数前面
int Plus(int one, int two);
}
}
3.添加一个类ComTest,继承接口IComTest,具体代码
using System.Runtime.InteropServices;
namespace ArwenAddCom
{
[Guid("04F4DC83-8883-4a03-BDBC-92D8630ECC1F")]
[ClassInterface(ClassInterfaceType.None)]
public class ComTest : IComTest
{
public int Plus(int a, int b)
{
return a + b ;
}
}
}
4.把AssemblyInfo.cs中的[assembly:ComVisible(false)]改成[assembly: ComVisible(true)].右击项目名打开属性窗口,点标签Build,选中Register for COMinterop.
如果不想把生成的dll共享,把它放到GAC中的程序集里.工作到此完成.点击build,在bin目录中会找到一个ArwenAddCom.dll文件.这个文件就是我们需要的com组件了.另外还会看到一个文件ArwenAddCom.tlb,正常情况应该有的.如果万一没这个tlb文件也可以后面通过一些命令调用dll文件去生成它.反正C++调用时dll,tlb文件是不能少的.
如果想把dll放到GAC中则还要做第五步后再build
5.生成snk文件,并添加到项目中(可选的步骤)
先打开VS命令窗口,有点像用cmd打开的dos窗口.在开始简单找到vs 2008,在visual studio tools下面有个Visual studio commandprompt.点击打开它
默认显示c:windowssystem32.你可以先切换到其他窗口.比如输入D:再回车就切换到D盘的路径下了再输入cd D:temp切换到temp目录.cd加任何路径就可以切换到d盘任何地方
然后输入命令sn–k ArwenAddCom.snk 再回车,就会在temp目录下生成一个snk文件.把ArwenAddCom.snk拷贝到项目的根目录中.和csproj文件相同的目录.
打开项目属性窗口,点标签Signing,选中Sign the assembly.并在下面的下拉列表中点browse,然后弹出一个对话框来,选中ArwenAddCom.snk
再次点build生成dll文件.
C++调用 C# com组件
1.调用前要先把com组件注册才行.
如果你刚调用dll和则build生成dll是在同一台电脑上则不用注册了.因为build C#的工程时选了Register for COMinterop.就自动给你注册了
如果不在同一台电脑上,那就要另外去注册,要真正开发桌面开发程序人家拿个安装程序去用时自然要重新注册的.这种情况下肯定不能手动注册,是通过写代码. 这里为了简单起见就只讲下怎么手动注册
跟生成snk文件一样要用到vs命令窗口.如果是没有用到snk文件的dll注册.先在vs命令窗口中把路径切换到开始生成的dll所在的目录.dll随便放哪都一样,只要找到那目录就行.
如果是是使用了snk文件,则通过gacutil /i ArwenAddCom.dll 将dll放入GAC中
再通过REGASM ArwenAddCom.dll /tlb:ArwenAddCom.tlb即可注册dll并生成tlb文件.
补充:
如果已经有tlb文件只注册的话就是REGASM ArwenAddCom.dll, 如果是单独想生成tlb文件是tlbexp /out:ArwenAddCom.tlb ArwenAddCom.dll.
另外还可以通过REGASM /regfile:ArwenAddCom.reg ArwenAddCom.dll生成一个reg注册脚本文件,你可以双击这个脚本文件去注册.
2.注册完了就可以在代码中用了,先新建一个C++ project,类型选Win32 Console Application
project名字取UseCsharpCom,在向导页面点finish.把ArwenAddCom.tlb文件拷贝到项目的任何目录下.我就放在D:UseCsharpComUseCsharpCom.我们会看到一个UseCsharpCom.cpp文件,双击打开把默认生成的代码全部删掉.敲入下面代码:
#include "stdafx.h"
#include
#import "..UseCsharpComCsharpComTest.tlb" named_guids raw_interfaces_only
void _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
CsharpComTest::IComTestPtr ptr; //类似明志一个指向接口的指针
ptr.CreateInstance(CsharpComTest::CLSID_ComTest); //实例化一个类
//这个地方有一点点奇怪我也还没弄懂.在C#中的函数是int Plus(int,int).但类型在这里都转成long了.另外就是我们不能直接
//来个long a = ptr->Plus(1,2);这样得不到a = 3,反正会出错.这里函数Plus的参数变成三个了long Plus(long,long,long *).其中最后一个指针得两数相加的结果
long a = 1;
long * lPtr = &a;
ptr->Plus(1,2,lPtr);
std::cout<<a;
}
如果前面把dll放到GAC中,此时就可以正确运行了.得到结果3
如果没有把dll放到GAC中,则必须把dll文件拷贝到有UseCsharpCom.exe这个文件的目录下.