C++是非托管代码,C#则是托管代码,无法直接调用
CLR的介绍见CLR简介
MSDN提到了两种非托管-托管的交互技术:CLR Interop和COM Interop
后者要将C# 类库注册为COM组件,本文只探讨CLR,要通过C++ CLR写中间层代码
方式一:组件A(C++ CLR App)->组件B(C# DLL)
方式二:组件A(C++ App)->组件B(C++ CLR DLL)->组件C(C# DLL)
步骤:
1、C++项目属性-“C/C++”-“公共语言运行时支持”-开启CLR
2、C++代码里通过#using "xxxx.dll"
调用C# dll
3、通过using namespace
引入C# dll中的命名空间
4、编写CLR代码,如MyClass里定义了一个加法函数和一个打印函数
#using "mycsdll.dll
using namespace MyClass;
using namespace System;
void main()
{MyClass^ dll = gcnew MyClass();//使用gcnew创建dll中的对象指针int resultInt = dll->Add(a, b);//调用dll对象中的方法String^ resultStr = gcnew String(resultInt.ToString());dll->Print(resultStr);
}
5、把C# dll拷贝至程序运行目录,通过SetDllDirectory设置dll路径不起作用
Debug运行程序,报错
托管调试助手 “LoaderLock”:“DLL“xxxxxxx.dll”正尝试在 OS 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内运行托管代码,这样做会导致应用程序挂起。”
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\crt\src\vcruntime\dll_dllmain.cpp
281行 result = DllMain(instance, reason, reserved);
解决办法
ctrl+alt+e,“异常”-“Managed Debuggin Assistants“-”LoaderLock”取消勾选
QT中调用C#的Dll
采用方式一:A(C++ CLR App)->C(C# DLL),在Qt项目里开启CLR,编译一堆报错
C:\Qt\Qt5.9.7\5.9.7\msvc2013_64\include\QtCore\qvector.h(73): error C2182: “t”: 非法使用“void”类型
C:\Qt\Qt5.9.7\5.9.7\msvc2013_64\include\QtCore\qvector.h(134): error C2182: “at”: 非法使用“void”类型
...
Qt的moc跟CLR原生有冲突,见How to use C# objects returned in QT
只能采用方式二,写一个C++ CLR DLL做中转
直接调用C#的exe
实测是不可行的,引用命名空间时提示找不到
不同版本VS的兼容性
如,通过VS2013编译的C++应用程序调用VS2019编译的C# Dll
汇总测试如下:
注:vs2013和vs2019均使用相同的.Net环境
测试条件 | 结果 |
---|---|
vs2013 c++ app -> vs2013 c++ clr dll -> vs2013 c# dll | pass |
vs2013 c++ app -> vs2013 c++ clr dll -> vs2019 c# dll | pass |
vs2013 c++ app -> vs2019 c++ clr dll -> vs2019 c# dll | failed |
说明C# dll的二进制兼容性只跟.Net版本相关,而C++ CLR跟VS(编译器)版本相关