现在手上有一个需求,需要通过C++去调用C#的方法。整个过程还是挺纷繁复杂的,在这做一点小小的记录。
整体的思路如下:
非托管C++ --> 托管C++ --> C#
因为非托管C++缺乏一些运行时的类库支持,所以需要借助于托管C++做一个wrapper
的活。
- 首先完成C#的开发,此时我们创建的是一个C#的动态链接库的项目
namespace CSharp
{
public class program
{
public void run() {
Console.WriteLine("CSharp is running");
}
}
}
- 托管C++编写
接下来就是托管C++的编写了,同样的,我们先创建一个动态链接库。
而后再进行C++项目的配置,如下所示
记得勾选公共语言运行时支持(/clr)
这一选项,下面的目标框架版本根据你的C#版本进行填写即可
接着在引用
中添加我们刚刚编写好的C#动态链接库,在引用的浏览
中找到C#动态链接库的路径,添加进去即可。
下面是我们的C++代码
#include "stdafx.h"
#include "mc.h"
#using "../demon/bin/Debug/cswcf.dll"
using namespace cswcf;
extern "C" __declspec(dllexport) void run() {
program ^a = gcnew program();
a->run();
}
注意这里需要使用using
引用到我们的C#DLL,再使用C#中的命名空间。
这里可能会遇到两个问题:
C++/CLI、C++/CX 或 OpenMP 不支持两阶段名称查找;请使用 /Zc:twoPhase-
这是一个跟C++模板相关的问题,因为我们的项目跟模板好像没啥关系,所以可以直接关闭掉。
项目->属性->C/C++->语言->符合模式:否
_DllMain@12”: 托管代码可能未运行在加载程序锁下,包括 DLL 入口点和从 DLL 入口点访问到的调用”
这个问题在微软家的文档中可以查看到。其实就是loaderLock
检测到有可能会导致死锁的问题存在,我们这里只是一个Demo,也直接关掉。直接打开dllmain.cpp
文件,然后在DllMain
上面添加#pragma unmanaged
即可。
- 非托管C++调用托管C++
非托管C++对托管C++的调用还有点小问题需要注意一下。除了属性中配置包含目录
和库目录
等常规操作外。需要将托管C++和C#等涉及到的一系列DLL放在非托管C++的执行文件目录下,才可以正常运行。