调用Visual C++ DLL时触发System.EntryPointNotFoundException的问题求助
调用Visual C++ DLL时触发System.EntryPointNotFoundException的问题求助
看起来你在C++ DLL和VB.NET互操作的时候踩了名字修饰和调用约定的坑,这是新手做跨语言调用时非常常见的问题,我来帮你一步步捋清楚怎么解决:
核心问题分析
C++编译器默认会给函数名做「名字修饰(Name Mangling)」,用来区分重载函数,但这会让VB.NET找不到正确的入口点;另外,调用约定(函数参数的传递方式、栈的清理规则)不匹配也会导致找不到入口或者调用崩溃。
第一步:修正C++ DLL的代码
最稳妥的写法是用extern "C"避免名字修饰,同时指定__stdcall调用约定(Windows平台默认调用约定,和VB.NET的DllImport默认规则一致,能减少很多出错概率)。
修改code.h:
#pragma once #include "pch.h" #ifndef ADD_CODE_H #define ADD_CODE_H // extern "C" 让编译器生成C风格的无修饰函数名 extern "C" { // __declspec(dllexport) 标记要导出的函数;__stdcall 统一调用约定 __declspec(dllexport) int __stdcall add_code(int lng); } #endif
修改code.cpp:
#include <iostream> #include "pch.h" #include "code.h" // 函数实现必须和头文件的调用约定完全匹配 int __stdcall add_code(int lng) { switch (lng) { case 4: return 1; case 5: return 2; default: return 9; } return 0; // 这里逻辑上永远到不了,保留也不影响 }
第二步:确认DLL的导出函数名
用VS自带的dumpbin工具查看导出的函数名,确保和我们预期的一致:
- 打开VS的开发者命令提示符(要对应你的编译平台,选x86或x64版本)
- 运行命令:
dumpbin /exports 你的DLL完整路径\MyDll.dll
这时候你会看到导出的函数名是_add_code@4(@4是__stdcall的标记,代表参数总字节数:int类型占4字节)。
第三步:VB.NET的调用代码
根据dumpbin查到的函数名,写正确的DllImport:
Imports System.Runtime.InteropServices Public Class MainForm ' 严格匹配导出的函数名和调用约定 <DllImport("MyDll.dll", EntryPoint:="_add_code@4", CallingConvention:=CallingConvention.StdCall)> Public Shared Function add_code(ByVal lng As Integer) As Integer End Function Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load Try Dim result As Integer = add_code(4) MessageBox.Show($"调用结果:{result}") ' 预期输出1 Catch ex As Exception MessageBox.Show($"出错了:{ex.Message}") End Try End Sub End Class
进阶优化:用DEF文件简化导出名
如果不想每次都写_add_code@4这种带后缀的名字,可以给C++项目加一个模块定义文件(.def),直接指定导出的函数名:
- 在C++项目里新建一个文本文件,命名为
MyDll.def - 写入内容:
LIBRARY MyDll EXPORTS add_code @1 ; @1是导出序号,可写可不写
- 在VS的项目属性中,把这个def文件添加到链接器->输入->模块定义文件中
这时候再用dumpbin看,导出的函数名就是add_code,VB.NET的代码可以简化成:
<DllImport("MyDll.dll", CallingConvention:=CallingConvention.StdCall)> Public Shared Function add_code(ByVal lng As Integer) As Integer End Function
关键注意事项
- 平台必须完全一致:C++ DLL编译的平台(x86/x64)必须和VB.NET项目的目标平台完全匹配,绝对不能用
Any CPU(否则在32位系统上跑32位,64位系统上跑64位,DLL不对应就会报错)。 - 调用约定要严格匹配:C用
__stdcall,VB.NET就用CallingConvention.StdCall;如果C用__cdecl,VB.NET必须指定CallingConvention.Cdecl,否则会出问题。 - DLL路径要正确:VB.NET运行时要能找到MyDll.dll,最简单的方法是把DLL复制到VB.NET项目的输出目录(比如
bin\x86\Debug)。
按照上面的步骤来,应该就能彻底解决你的System.EntryPointNotFoundException问题啦!




