C#调用C++ DLL需通过P/Invoke并导出C接口。使用extern “C”和__declspec(dllexport)避免名字修饰,C#中用[DllImport]声明函数,指定CallingConvention.Cdecl、CharSet.Ansi及StringBuilder处理字符串。结构体需用[StructLayout(Sequential)]保证内存布局一致。确保DLL位于输出目录且平台匹配(x86/x64),避免入口点找不到或崩溃问题。

在 C# 中调用 C++ 编写的 DLL,核心在于使用 平台调用服务(P/Invoke)。由于 C++ 编译后的函数名会经过修饰(name mangling),且不支持直接导出托管接口,因此不能像调用 C 风格 DLL 那样简单。本文将一步步说明如何从 C++ 创建可被 C# 调用的 DLL,并在 C# 中成功调用。
1. 编写兼容的 C++ DLL(导出 C 接口)
要让 C# 能调用,C++ DLL 必须以 C 语言方式导出函数,避免 C++ 的名字修饰问题。使用 extern “C” 和 __declspec(dllexport) 声明函数。
// MathLibrary.h
extern "C" { __declspec(dllexport) int Add(int a, int b); __declspec(dllexport) double Multiply(double x, double y); __declspec(dllexport) void GetString(char* buffer, int bufferSize);}
// MathLibrary.cpp
立即学习“C++免费学习笔记(深入)”;
#include "MathLibrary.h"#includeint Add(int a, int b) {return a + b;}
double Multiply(double x, double y) {return x * y;}
void GetString(char buffer, int bufferSize) {const char str = "Hello from C++!";strncpy_s(buffer, bufferSize, str, strlen(str));}
编译为 DLL: 在 Visual Studio 中创建“动态链接库 (DLL)”项目,生成 MathLibrary.dll。
2. 在 C# 中声明并调用 DLL 函数
C# 使用 [DllImport] 特性导入非托管函数。注意数据类型映射和字符串处理。
using System;using System.Runtime.InteropServices;class Program{// 声明 C++ 导出的函数[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl)]public static extern int Add(int a, int b);
[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl)]public static extern double Multiply(double x, double y);[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]public static extern void GetString(StringBuilder buffer, int bufferSize);static void Main(){ // 调用整数函数 int result1 = Add(5, 3); Console.WriteLine($"Add(5, 3) = {result1}"); // 调用浮点函数 double result2 = Multiply(4.5, 2.0); Console.WriteLine($"Multiply(4.5, 2.0) = {result2}"); // 调用返回字符串的函数 var sb = new StringBuilder(256); GetString(sb, sb.Capacity); Console.WriteLine($"String from C++: {sb.ToString()}");}
}
关键点说明:
CallingConvention.Cdecl:C++ 默认使用 Cdecl 调用约定,必须匹配。StringBuilder:用于接收 C++ 写入的字符串缓冲区。CharSet = CharSet.Ansi:确保使用 ANSI 字符集而非 Unicode。DLL 文件需放在 C# 程序的运行目录下(如 binDebug)。
3. 处理复杂类型(结构体传递)
若需传递结构体,需在 C# 中定义内存布局一致的结构,并使用 [StructLayout]。
// C++ 结构体
struct Point { int x; int y;};extern "C" {__declspec(dllexport) double DistanceFromOrigin(Point p);}
// C# 对应结构体
[StructLayout(LayoutKind.Sequential)]public struct Point{ public int x; public int y;}[DllImport("MathLibrary.dll", CallingConvention = CallingConvention.Cdecl)]public static extern double DistanceFromOrigin(Point p);
调用方式:
Point pt = new Point { x = 3, y = 4 };double dist = DistanceFromOrigin(pt);Console.WriteLine($"Distance: {dist}");
4. 常见问题与解决方案
找不到 DLL:确认 DLL 位于输出目录,或使用绝对路径。无法解析入口点:检查函数名是否被 C++ 修饰,确保使用 extern "C" 导出。崩溃或乱码:检查调用约定、字符集、缓冲区大小是否匹配。x86/x64 不匹配:C++ DLL 与 C# 程序目标平台必须一致(都选 x64 或都选 x86)。
基本上就这些。只要 C++ 暴露的是 C 风格接口,C# 就能通过 P/Invoke 可靠调用。关键是保持调用约定、数据类型和内存管理的一致性。调试时可用工具如 Dependency Walker 或 dumpbin /exports 查看 DLL 导出函数名。
以上就是C# 如何调用 C++ 编写的 DLL_C# 调用 C++ DLL 完整教程的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1442211.html
微信扫一扫
支付宝扫一扫