C++调用C#dll

来源:互联网 发布:祖马龙 知乎 编辑:程序博客网 时间:2024/06/07 01:40

C++调用C#需要使用托管代理。


一、添加C# DLL

#using "../debug/BenQGuru.eMES.DLLService.dll"using namespace BenQGuru::eMES::DLLService;


托管调用时,使用的是#using “文件路径”,using namespace 后面在C#中是 BenQGuru.eMES.DLLService.dll ,但是在C++中编译不能识别点(.),用::代替变成
BenQGuru::eMES::DLLService;


二、配置属性

如果没有设置则报如下错误,托管代码中需要用到CLR语言,需要这里进行设置

1>e:\test\testctocc\testctocc\testctocc.cpp(11): fatal error C1190: 托管目标代码需要“/clr”选项



如图所示设置为MDd,如果没有设置则报如下错误

MDd为Debug multiThread(dynamic link) MDd msvertd.lib,如是release就选择MD,在托管中CLR编译器需要动态调用系统dll,静态调用会使连接的CRT,代理无法拦截。

1>cl : 命令行 error D8016: “/clr”和“/MTd”命令行选项不兼容 


CLE需要动态调用,MFC的使用也得设置为共享DLL。


三、调用DLL里面的函数

配置完成后就开始使用,代码如下:

        #include <msclr\marshal_cppstd.h>  extern "C"  int __stdcall SetImeiInfo(char *a,char *b,char *c){        MESHelper ^MESdll = gcnew MESHelper();System::String^ stro_c;char* rtnValue;String^ str_a= System::Runtime::InteropServices::Marshal::PtrToStringAnsi((IntPtr)a); String^ str_b= System::Runtime::InteropServices::Marshal::PtrToStringAnsi((IntPtr)b); MESdll->SetIMEIInfo(str_a, str_b, stro_c);        rtnValue = (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(stro_c);     strcpy(c, rtnValue);        return 0;}
我的BenQGuru.eMES.DLLService.dll里面有 MESHelper类。

这里的创建堆内存跟原来的是不一样的,托管调用的时候地址是用帽子(^)去代替星星的(*)的,而且new也被gcnew所代替。

在托管中,C#的参数类型跟C++的不一样,需要进行转换,调用C#的dll时,对应的c#的string这里需要采用System::String的方法进行调用,由于本人平时比较多的使用Char

类型,这里只提供Char转System::String。


包含系统头文件msclr\marshal_cppstd.h

代码中:String^ strSN= System::Runtime::InteropServices::Marshal::PtrToStringAnsi((IntPtr)SN);
是由chr*型 转化为C#的System::String为函数提供参数。


代码中:rtnValue = (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(stroErrMSG);

由于C#有out类型的返回值,我们需要获取函数返回来的值,就需要把System::String转换为Char*,

注意一个小基础:代码中返回来的str0_c是一个地址,不要把一个地址直接赋值于一个地址,这样会导致你调用此函数时返回去的值为空,需要把参数c的内存地址里的值进行赋值。




































原创粉丝点击