You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

调用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工具查看导出的函数名,确保和我们预期的一致:

  1. 打开VS的开发者命令提示符(要对应你的编译平台,选x86或x64版本)
  2. 运行命令:
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),直接指定导出的函数名:

  1. 在C++项目里新建一个文本文件,命名为MyDll.def
  2. 写入内容:
LIBRARY MyDll
EXPORTS
    add_code @1  ; @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

关键注意事项

  1. 平台必须完全一致:C++ DLL编译的平台(x86/x64)必须和VB.NET项目的目标平台完全匹配,绝对不能用Any CPU(否则在32位系统上跑32位,64位系统上跑64位,DLL不对应就会报错)。
  2. 调用约定要严格匹配:C__stdcall,VB.NET就用CallingConvention.StdCall;如果C__cdecl,VB.NET必须指定CallingConvention.Cdecl,否则会出问题。
  3. DLL路径要正确:VB.NET运行时要能找到MyDll.dll,最简单的方法是把DLL复制到VB.NET项目的输出目录(比如bin\x86\Debug)。

按照上面的步骤来,应该就能彻底解决你的System.EntryPointNotFoundException问题啦!

火山引擎 最新活动