![](/img/trans.png)
[英]DLL EntryPointNotFoundException when trying to import C/C++ DLL into C#
[英]EntryPointNotFoundException when binding C++ dll in C#
我嘗試在我的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));
}
}
}
什么是不正確的?
您可以嘗試在類外聲明函數,並使用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));
}
}
}
在這種情況下,您可以下載Dependency Walker ,將DLL加載到其中並查看“導出函數”列表。 您也可以使用DumpBin 。
默認情況下,從C ++或C DLL導出的函數使用名稱修飾 (也稱為名稱管理 )。
正如在MSDN上所說:
C ++函數的修飾名稱包含以下信息:
- 功能名稱。
- 函數所屬的類,如果是成員函數。 這可能包括包含函數類的類,依此類推。
- 函數所屬的命名空間(如果它是命名空間的一部分)。
- 函數參數的類型。
- 召喚大會。
- 函數的返回類型。
例如, Add
函數的裝飾名稱將類似於Add@MyMathFuncs@MathFuncs@@SANNN@Z
但正如Darin Dimitrov所建議的那樣,通過將函數和任何函數原型包含在extern "C" {…}
塊中,可以強制C ++編譯器公開C ++函數的未修飾名稱。
雖然如果您要使用第三方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.