簡體   English   中英

在C#中綁定C ++ DLL時的EntryPointNotFoundException

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM