简体   繁体   English

在C#中绑定C ++ DLL时的EntryPointNotFoundException

[英]EntryPointNotFoundException when binding C++ dll in C#

I try to bind a simple c++ dll shown in http://msdn.microsoft.com/en-us/library/ms235636.aspx in my c# console app, but I get a EntryPointNotFoundException for Add within dll at runtime. 我尝试在我的c#控制台应用程序中绑定http://msdn.microsoft.com/en-us/library/ms235636.aspx中显示的简单c ++ dll,但是在运行时我在dll中得到了一个EntryPointNotFoundException。 My test class is 我的测试课是

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));
        }
    }
}

What is not correct? 什么是不正确的?

You could try declaring the functions outside of a class and also exporting them with extern "C" : 您可以尝试在类外声明函数,并使用extern "C"导出它们:

Header: 标题:

// 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);
}

Implementation: 执行:

// 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;
    }
}

Calling code: 来电代码:

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));
        }
    }
}

In cases such as this, you can download Dependency Walker , load your DLL into it and look at the Export Functions list. 在这种情况下,您可以下载Dependency Walker ,将DLL加载到其中并查看“导出函数”列表。 You can also use DumpBin for this. 您也可以使用DumpBin

By default, function exported from a C++ or C DLL are using Name Decoration (also called Name Mangling ). 默认情况下,从C ++或C DLL导出的函数使用名称修饰 (也称为名称管理 )。

As said on MSDN : 正如在MSDN上所说:

A decorated name for a C++ function contains the following information: C ++函数的修饰名称包含以下信息:

  • The function name. 功能名称。
  • The class that the function is a member of, if it is a member function. 函数所属的类,如果是成员函数。 This may include the class that encloses the function's class, and so on. 这可能包括包含函数类的类,依此类推。
  • The namespace the function belongs to (if it is part of a namespace). 函数所属的命名空间(如果它是命名空间的一部分)。
  • The types of the function's parameters. 函数参数的类型。
  • The calling convention. 召唤大会。
  • The return type of the function. 函数的返回类型。

So decorated name for your Add function, for example, will look like Add@MyMathFuncs@MathFuncs@@SANNN@Z . 例如, Add函数的装饰名称将类似于Add@MyMathFuncs@MathFuncs@@SANNN@Z

But it is possible to force the C++ compiler to expose undecorated names for C++ functions by enclosing the function, and any function prototypes, within an extern "C" {…} block, as Darin Dimitrov suggested. 但正如Darin Dimitrov所建议的那样,通过将函数和任何函数原型包含在extern "C" {…}块中,可以强制C ++编译器公开C ++函数的未修饰名称。

Although if you're going to use a third-party DLL (so you can't modify it) or you just don't want to expose decorated names for some reason, you can specify the function's name explicitly: 虽然如果您要使用第三方DLL(因此无法修改它),或者您只是因某些原因不想公开装饰名称,您可以明确指定该函数的名称:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM