在 C# 中绑定 C++ dll 时出现 EntryPointNotFoundException

Posted

技术标签:

【中文标题】在 C# 中绑定 C++ dll 时出现 EntryPointNotFoundException【英文标题】:EntryPointNotFoundException when binding C++ dll in C# 【发布时间】:2012-10-05 05:29:50 【问题描述】:

我尝试在我的 c# 控制台应用程序中绑定http://msdn.microsoft.com/en-us/library/ms235636.aspx 中显示的简单 c++ dll,但我在运行时在 dll 中添加一个 EntryPointNotFoundException。我的测试课是

namespace BindingCppDllExample

    public class BindingDllClass
    
        [DllImport("MathFuncsDll.dll")]
        public static extern double Add(double a, double b);
    

    public class Program
    
        public static void Main(string[] args)
        
            double a = 2.3;
            double b = 3.8;
            double c = BindingDllClass.Add(a, b);

            Console.WriteLine(string.Format("0 + 1 = 2", a, b, c));
        
    

什么不正确?

【问题讨论】:

可能重复:***.com/questions/5877349/… 我猜你的 CallingConvention 不匹配。我还假设 MathFuncsDll.dll 没有将名为 Add 的方法声明为可导出。 【参考方案1】:

您可以尝试在类之外声明函数并使用extern "C" 导出它们:

标题:

// MathFuncsDll.h
namespace MathFuncs

    // Returns a + b
    extern "C" __declspec(dllexport) double Add(double a, double b);

    // Returns a - b
    extern "C" __declspec(dllexport) double Subtract(double a, double b);

    // Returns a * b
    extern "C" __declspec(dllexport) double Multiply(double a, double b);

    // Returns a / b
    // Throws DivideByZeroException if b is 0
    extern "C" __declspec(dllexport) double Divide(double a, double b);

实施:

// MyMathFuncs.cpp
#include "MathFuncsDll.h"
#include <stdexcept>

using namespace std;

namespace MathFuncs

    double Add(double a, double b)
    
        return a + b;
    

    double Subtract(double a, double b)
    
        return a - b;
    

    double Multiply(double a, double b)
    
        return a * b;
    

    double Divide(double a, double b)
    
        if (b == 0)
        
            throw new invalid_argument("b cannot be zero!");
        

        return a / b;
    

调用代码:

namespace BindingCppDllExample

    public class BindingDllClass
    
        [DllImport("MathFuncsDll.dll")]
        public static extern double Add(double a, double b);
    

    public class Program
    
        public static void Main(string[] args)
        
            double a = 2.3;
            double b = 3.8;
            double c = BindingDllClass.Add(a, b);

            Console.WriteLine(string.Format("0 + 1 = 2", a, b, c));
        
    

【讨论】:

谢谢!但是,如果我有大型类,我将不得不包装我想使用的所有方法,不是吗? 您可以在命名空间中组织它们。我认为您不能使用 P/Invoke 调用 C++ 类方法,因为创建 P/Invoke 是为了调用任何非托管代码(包括不存在类概念的纯 C)。因此,您仍然可以在非托管代码中使用类,但只公开需要从托管代码中调用的函数。【参考方案2】:

在这种情况下,您可以下载Dependency Walker,将您的 DLL 加载到其中并查看导出函数列表。您也可以为此使用DumpBin。

默认情况下,从 C++ 或 C DLL 导出的函数使用Name Decoration(也称为Name Mangling)。

如MSDN所说:

C++ 函数的修饰名称包含以下内容 资料:

函数名。 函数所属的类(如果它是成员函数)。这可能包括包含函数类的类,等等。 函数所属的命名空间(如果它是命名空间的一部分)。 函数参数的类型。 调用约定。 函数的返回类型。

例如,Add 函数的修饰名称将类似于 Add@MyMathFuncs@MathFuncs@@SANNN@Z

但可以强制 C++ 编译器通过将函数和任何函数原型封装在 extern "C" … 块中来公开 C++ 函数的未修饰名称,正如 Darin Dimitrov 所建议的那样。

虽然如果你打算使用第三方 DLL(所以你不能修改它)或者你只是出于某种原因不想暴露修饰的名字,你可以明确地指定函数的名字:

[DllImport("MathFuncsDll.dll", EntryPoint = "Add@MyMathFuncs@MathFuncs@@SANNN@Z")]
public static extern double Add(double a, double b);

【讨论】:

我使用了dumpbin,但不知道如何处理它。感谢 EntryPoint 的好建议

以上是关于在 C# 中绑定 C++ dll 时出现 EntryPointNotFoundException的主要内容,如果未能解决你的问题,请参考以下文章

从 C# 调用 C++ dll 函数时出现问题

将数组移交给 C# 中动态加载的 C++ DLL 时出现 System.AccessViolationException

使用 C# 访问非托管 C++ DLL 时出现 AccessViolationException

尝试从 C# 调用 C++ dll 时出现格式不正确的异常

C# 和 C++ dll - 编组字符串

在托管 DLL 中加载 C++ DLL 时出现 EEFileLoadException