1.简介
本文介绍了一种如何在C#中使用C++DLL的方法。托管的C++可以方便的被C#调用,而非托管的C++可以使用托管C++进行封装然后再调用。本文只介绍此种写法,并未介绍使用dllimport方式调用的写法。
2.环境
VS2017
.NET Framework 4.6.2
Win10(版本 10.0.17134 )
3.创建项目
3.1.C#项目
打开VS,新建.NET Framework 控制台程序“CSharpUsingManagedCpp”。

图 1
3.2.C++项目
在解决方案下添加C++ DLL项目“ManagedCpp”。

图 2
4.编写C++代码
4.1.非托管C++
在ManagedCpp项目下添加新类“Test”,用于模拟被调用的非托管C++。

图 3
Test类在初始化时给定一个数值,然后在Calc方法中计算该值与Calc方法中传递的参数的乘积,并返回乘积结果。
Test类的头文件和源文件分别如下:
1 | `//Test.h #pragma once class Test { private: int m_multiple; public: Test(int multiple); int Calc(int value); }; //Test.cpp #include "stdafx.h" #include "Test.h" #include <iostream> using namespace std; Test::Test(int multiple) { m_multiple = multiple; } int Test::Calc(int value) { const int calcResult = m_multiple * value; cout << "c++ out:"<< calcResult <<endl; return calcResult; }` |
4.2.托管C++
Test类主要用于模拟原来C++,接着我们使用托管c++对其进行包装,用于C#调用。
首先,打开“ManagedCpp”项目的属性,修改“公共语言运行时支持”为“公共语言运行时支持(/clr)”。

图 4
然后,添加新的源文件“CppPackage.cpp”或者类,此处仅添加了一个新的源文件。在“CppPackage.cpp”中编写代码:
1 | `#include "stdafx.h" #include "Test.h" namespace ManagedCpp { public ref class CppPackage { private: Test * _test; public: //下面两个方法分别是托管类的构造和析构方法 CppPackage(int multiple) { _test = new Test(multiple); } ~CppPackage() { delete _test; } int Calc(int value) { return _test->Calc(value); } }; }` |
4.3.其他配置项修改
- 关于警告C4747或者LoaderLock错误。
打开“dllmain.cpp”,在DllMain方法前添加指令“#pragma unmanaged”。如果不添加此指令,编译器会报警告C4747:“warning C4747: 调用托管“_DllMain@12”: 托管代码可能未运行在加载程序锁下,包括 DLL 入口点和从 DLL 入口点访问到的调用”;在C#中使用时会报错:托管调试助手 “LoaderLock”:”DLL“****\ManagedCpp.dll”正尝试在 OS 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内运行托管代码,这样做会导致应用程序挂起。”。
有其他人提到关闭LoaderLock,这个方法不会提示报错,但是也不会输出结果。
2)关于警告C4199
将项目属性中C/C++、语言下的符合模式修改为“否”,这样可以让编译器不发出警告C4199“warning C4199: C++/CLI、C++/CX 或 OpenMP 不支持两阶段名称查找;请使用 /Zc:twoPhase-”,这也有可能导致C#使用时出错。

图 5
5.C#调用
首先添加对C++项目ManagedCpp(或者ManagedCpp.dll)的引用。
然后在C#项目“CSharpUsingManagedCpp”中的main函数编写如下代码(注意添加引用“using ManagedCpp;”),运行即可看到结果如图6所示。
1 | `static void Main(string[] args) { int multiple = 10; CppPackage cppPackage = new CppPackage(multiple); var calcResult = cppPackage.Calc(2); Console.WriteLine($"calcResult:{calcResult}"); Console.WriteLine("Finish!"); Console.Read(); }` |

图 6
6.Demo下载
注意,下载过后可能需要配置C++项目中的属性“Windows SDK版本”。