c# 如何调用c++的dll
技术百科
幻夢星雲
发布时间:2026-01-24
浏览: 次 C#调用C++ DLL需用DllImport声明,C++须用extern "C"和__declspec(dllexport)导出C风格函数,平台、调用约定、路径、字符串/结构体内存布局必须严格一致,否则引发DllNotFound、EntryPointNotFound或访问冲突等错误。
用 DllImport 声明函数,不是“引用”或“添加引用”
你不能像引用 .NET 程序集那样直接“添加引用”C++ DLL。C# 调用 C++ DLL 的核心机制是平台调用(P/Invoke),靠 DllImport 特性显式声明外部函数签名。如果直接把 C++ DLL 拖进项目或右键“添加引用”,会失败——它不是托管程序集。
关键前提:C++ DLL 必须导出 C 风格函数(即用 extern "C" 和 __declspec(dllexport)),否则 C# 找不到符号(常见错误:System.EntryPointNotFoundException)。
- 确保 C++ 函数不带 C++ name mangling:在头文件中写
extern "C" __declspec(dllexport) int add(int a, int b); - 编译为 x86 或 x64 时,C# 项目平台必须严格匹配(
AnyCPU默认可能失败,建议显式设为x64或x86) - DLL 文件需放在运行时能被找到的位置:与 exe 同目录、
PATH环境变量路径,或用SetDllDirectory指定
DllImport 的路径和调用约定不能写错
路径写相对路径(如 "MyNative.dll")比绝对路径更安全;调用约定(CallingConvention)必须和 C++ 导出函数一致,默认是 __cdecl,但 Windows API 风格常用 __stdcall。写错会导致栈失衡、崩溃或返回值异常(比如始终返回 0)。
常见组合:
- C++ 用
__declspec(dllexport) int func(...);→ C# 用CallingConvention = CallingConvention.Cdecl(默认可省略) - C++ 用
__declspec(dllexport) int __stdcall func(...);→ C# 必须显式写CallingConvention = CallingConvention.StdCall - 路径中不要写
.dll后缀(即可,运行时自动补)
DllImport("MyNative")
字符串、数组、结构体传参要特别小心内存布局
C# 和 C++ 对字符串、指针、结构体的默认处理完全不同。直接传 string 或 int[] 很容易引发访问冲突或乱码。
- 传字符串给 C++:C# 侧用
[MarshalAs(UnmanagedType.LPStr)]或[MarshalAs(UnmanagedType.LPWStr)]明确编码,C++ 接收const char*或const wchar_t* - 传结构体:C# 结构体必须加
[StructLayout(LayoutKind.Sequential)],字段顺序、对齐(Pack=1)要和 C++ 一致;避免使用string字段,改用固定长度char[256]+[MarshalAs] - 输出缓冲区(如 C++ 写入 char*):C# 用
StringBuilder并预先.Capacity,而非string
[DllImport("MyNative.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetString([MarshalAs(UnmanagedType.LPStr)] StringBuilder buffer, int bufferSize);调试时最常见的三个错误现象及定位方式
不是所有报错都提示“找不到 DLL”——很多崩溃发生在调用瞬间,没堆栈或只有 AccessViolationException。
-
DllNotFoundException:DLL 文件根本没找到。用Process Monitor过滤进程名,看它尝试加载了哪些路径 -
EntryPointNotFoundException:函数名不匹配。用dumpbin /exports MyNative.dll查真实导出名(注意是否有前导下划线或 @ 后缀) - 程序闪退 / 异常退出(无异常抛出):大概率是调用约定错、结构体布局错、或 C++ 释放了 C# 分配的内存(反之亦然)。启用非托管代码调试(项目属性 → 调试 → 勾选“启用本机代码调试”)
真正麻烦的从来不是“怎么写第一行 DllImport”,而是让两边的数据解释方式严丝合缝。一个字节对齐差异、一个字符串编码误判,就足以让调用看起来“成功”却返回垃圾值。
# 放在
# 找不到
# windows
# 你不
# 而非
# 很容易
# 下划线
# 右键
# 设为
# win
# 环境变量
# 堆
# c++
# String
# int
# 编码
# 字节
# 指针
# c#
# 字符串
# .net
# 报错
# access
# 栈
# lsp
# 结构体
# extern
# char
# const
# 严丝合缝
# wchar_t
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win10系统字体模糊怎么办_Windows10高
- PHP怎么接收前端传的时间戳_处理时间戳参数转换技
- 如何在 Pandas 中按元素交集合并两列字符串
- Win11如何设置ipv6 Win11开启IPv6
- Win10怎样清理C盘爱奇艺缓存_Win10清理爱
- Win11怎么设置默认邮件客户端 Win11修改M
- 如何在Golang中处理JSON字段缺失_Gola
- 如何使用Golang实现容器安全扫描_Golang
- Go语言中CookieJar的持久化机制解析:内存
- C++如何使用Qt创建第一个GUI窗口?(入门教程
- 如何优化Golang Web性能_Golang H
- c++中的CRTP是什么 c++奇异递归模板模式【
- Python与MongoDB NoSQL开发实战_
- windows如何禁用驱动程序强制签名_windo
- Python正则表达式实战_模式匹配说明【教程】
- Mac怎么设置登录项_Mac管理开机自启动程序【教
- C++中的std::shared_from_thi
- c++23 std::expected怎么用 c+
- 如何使用Golang实现错误包装与传递_Golan
- Windows10无法识别USB设备描述符请求失败
- 怎么将XML数据可视化 D3.js加载XML
- 如何在Golang中处理二进制数据_Golang
- 如何使用Golang反射创建map对象_动态生成键
- 如何在网页无标准表格标签时高效提取结构化数据
- c++获取当前时间戳_c++ time函数使用详解
- Win10怎样清理C盘Steam游戏缓存_Win1
- Win11搜索栏无法输入_解决Win11开始菜单搜
- Win11怎么关闭系统透明度_Windows11个
- php485函数怎么捕获异常_php485错误处理
- Windows11怎么自定义任务栏_Windows
- ACF 教程:如何正确更新嵌套在多层 Group
- Win10闹钟铃声怎么自定义 Win10闹钟自定义
- mac怎么安装pip_MAC Python pip
- Python变量绑定机制_引用模型解析【教程】
- 如何使用Golang匿名函数_快速定义临时函数逻辑
- Windows如何使用注册表查找和删除项?(reg
- Python迭代器生成器进阶教程_节省内存与懒加载
- XSLT怎么生成动态的HTML属性名和标签名
- Win11讲述人怎么关闭_Win11误触开启语音朗
- Windows 11如何开启文件夹加密(EFS)_
- Win11怎么关闭任务栏小图标_Windows11
- php怎么下载安装后测试是否成功_简单脚本验证方法
- 如何在JavaScript中动态拼接PHP的bas
- Win11怎么关闭搜索历史_Win11清除任务栏搜
- php中常量能用::访问吗_类常量与作用域操作符使
- C++中引用和指针有什么区别?(代码说明)
- Win11系统更新后黑屏怎么办 Win11更新黑屏
- php和redis连接超时怎么办_phpredis
- Win11怎么关闭内容自适应亮度_Windows1
- Win11相机打不开提示错误怎么修_相机权限开启与


QQ客服