在C#项目中调用C++ DLL时遭遇System.DllNotFoundException错误的排查求助
解决加载Melpe.dll时的System.DllNotFoundException问题
我在C#项目调用C++ DLL时也遇到过好几次这种问题,咱们一步步来排查最可能的原因:
1. 确认DLL路径可访问
你现在用的是绝对路径D:\\Debug\\Melpe.dll,首先要确认这个路径下确实存在该DLL文件。更稳妥的做法是把Melpe.dll直接复制到你的C#项目输出目录(通常是bin\Debug或bin\Release),然后简化DllImport只写文件名:
[DllImport("Melpe.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void voc_init_decode(short vocrate);
这样程序运行时会自动从当前工作目录(项目输出文件夹)加载DLL,避免固定绝对路径带来的环境差异问题。
2. 匹配32位/64位架构
这是最容易被忽略的关键点:
- 先确认你的Melpe.dll是编译为x86(32位)还是x64(64位)
- 打开C#项目属性 → 生成 → 将平台目标设置为和DLL一致的架构。别用“Any CPU”——如果你的DLL是32位,64位系统上的C#进程(来自Any CPU设置)会无法加载它。
3. 检查是否缺失依赖库
C编译的DLL几乎都依赖微软的Visual C运行时库(比如vcruntime140.dll或msvcr100.dll)。你可以这样检查依赖:
- 打开Visual Studio开发者命令提示符,运行:
dumpbin /dependents D:\Debug\Melpe.dll - 如果有依赖库显示“未找到”,安装对应的VC++可再发行组件包(注意要选和DLL架构匹配的32位或64位版本)。
4. 确保导出函数名匹配
从你的反汇编结果来看,实际导出的函数名是带下划线的:_voc_docode、_voc_encode等,但你在DllImport里用的是不带下划线的名字。对于Cdecl调用约定,这种名称不匹配会导致即使DLL能找到,也找不到对应的函数。你可以通过指定入口点来修复:
[DllImport("Melpe.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "_voc_docode")] public static extern void voc_docode(byte[] input, short[] sp_out);
(顺便说一句:我这里也修正了sp_out的类型——后面会详细讲这个问题)
额外提醒:修正参数类型不匹配
虽然这不是导致当前DLL加载失败的原因,但一旦DLL加载成功,类型不匹配会引发崩溃或错误结果:
- 原C++的
voc_encode中sp_in是Shortword[](也就是short数组),但你C#里用的是byte[],要改成short[]。 - 同样,
voc_docode的sp_out也应该是short[],而不是byte[]。
把这些声明更新为匹配C++的类型:
[DllImport("Melpe.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "_voc_encode")] public static extern void voc_encode(short[] sp_in, byte[] output, bool npp_flag); [DllImport("Melpe.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "_voc_docode")] public static extern void voc_docode(byte[] input, short[] sp_out);
按照这些步骤逐一排查,你应该能解决DllNotFoundException问题,让C#代码正确调用C++函数。
内容的提问来源于stack exchange,提问作者Pedram
相关产品推荐
相关产品推荐

