在 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 时出现 System.AccessViolationException