ale*_*555 10 c# dllimport entrypointnotfoundexcept
我尝试在我的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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
什么是不正确的?
Dar*_*rov 18
您可以尝试在类之外声明函数,并使用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);
}
Run Code Online (Sandbox Code Playgroud)
执行:
// 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;
}
}
Run Code Online (Sandbox Code Playgroud)
来电代码:
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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您可以下载Dependency Walker,将DLL加载到其中并查看"导出函数"列表.您也可以使用DumpBin.
默认情况下,从C++或C DLL导出的函数使用名称修饰(也称为名称管理).
正如在MSDN上所说:
C++函数的修饰名称包含以下信息:
- 功能名称.
- 函数所属的类,如果它是成员函数.这可能包括包含函数类的类,依此类推.
- 函数所属的命名空间(如果它是命名空间的一部分).
- 函数参数的类型.
- 召唤大会.
- 函数的返回类型.
Add例如,您的功能的装饰名称将如下所示Add@MyMathFuncs@MathFuncs@@SANNN@Z.
但extern "C" {…}正如Darin Dimitrov所建议的那样,通过将一个函数和任何函数原型包含在一个块中,可以强制C++编译器公开C++函数的未修饰名称.
虽然如果您要使用第三方DLL(因此无法修改它),或者您只是因某些原因不想公开装饰名称,您可以明确指定该函数的名称:
[DllImport("MathFuncsDll.dll", EntryPoint = "Add@MyMathFuncs@MathFuncs@@SANNN@Z")]
public static extern double Add(double a, double b);
Run Code Online (Sandbox Code Playgroud)