1

我正在尝试将一些用非托管 C++ 编写的 32 位和 64 位 DLL 导入到我的 C# 项目中。作为示例,我这样做了:

C++ DLL 函数

long mult(int a, int b) {
    return ((long) a)*((long) b);
}

C# 代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication2
{
    class DynamicDLLImport
    {
        private IntPtr ptrToDll;
        private IntPtr ptrToFunctionToCall;

        [DllImport("kernel32.dll")]
        public static extern IntPtr LoadLibrary(string dllToLoad);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

        [DllImport("kernel32.dll")]
        public static extern bool FreeLibrary(IntPtr hModule);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate int Multiply(int a, int b);
        private Multiply multiply;

        public DynamicDLLImport(string dllName)
        {
            ptrToDll = LoadLibrary(dllName);
            // TODO: Error handling.

            ptrToFunctionToCall = GetProcAddress(ptrToDll, "mult");
            // TODO: Error handling.

            // HERE ARGUMENTNULLEXCEPTION
            multiply = (Multiply)Marshal.GetDelegateForFunctionPointer(ptrToFunctionToCall, typeof(Multiply));
        }

        public int mult_func(int a, int b)
        {
            return multiply(a, b);
        }

        ~DynamicDLLImport()
        {
            FreeLibrary(ptrToDll);
        }
    }

    class DLLWrapper
    {
        private const string Sixtyfour = "c:\\Users\\Hattenn\\Documents\\Visual Studio 2010\\Projects\\ConsoleApplication2\\ConsoleApplication2\\easyDLL0_64.dll";
        private const string Thirtytwo = "c:\\Users\\Hattenn\\Documents\\Visual Studio 2010\\Projects\\ConsoleApplication2\\ConsoleApplication2\\easyDLL0.dll";
//        [DllImport(Sixtyfour)]
//        public static extern int mult(int a, int b);
        [DllImport(Thirtytwo)]
        public static extern int mult(int a, int b);
    }

    class Program
    {
        static void Main(string[] args)
        {
            int a = 5;
            int b = 4;
            DynamicDLLImport dllimp = new DynamicDLLImport("easyDLL0.dll");

            Console.WriteLine(DLLWrapper.mult(a, b));
            //Console.WriteLine(dllimp.mult_func(a, b));

            Console.ReadKey();
        }
    }
}

我似乎无法让它工作。以下是我收到的错误消息:

  1. 当我将 DLLWrapper 类与 32 位 DLL 文件一起使用时,我得到“DLLNotFoundException”,但 DLL 文件正是在该路径中。
  2. 当我将 DLLWrapper 类与 64 位 DLL 文件一起使用并将“平台目标”属性更改为“x64”时,我得到相同的“DLLNotFoundException”,如果我尝试使用“x86”构建,那么我得到“BadImageException”。
  3. 当我使用 DynamicDLLImport 类时,我总是在代码中用“HERE ARGUMENTNULLEXCEPTION”注释的那一行得到“ArgumentNullException”。

我究竟做错了什么?

4

4 回答 4

1

您是如何从 DLL 中导出函数的?Windows DLL 不会自动导出所有函数,并且 C++ 会修饰名称,例如区分函数重载,除非你告诉它不要这样做,但编译器具体如何,其他语言肯定不理解它。

您可以通过启动 Visual Studio 命令提示符并使用命令进行检查

dumpbin /EXPORTS "your library.dll"
于 2012-07-17T10:28:48.273 回答
1

The problem turned out to be that the dll was deployed in debug mode and not in a correct way. When it was deployed in release mode, everything seemed to work fine. Anyone having a similar problem should know that compiling the dll in debug mode and just copying it to another computer is not the right way to do it.

于 2012-08-08T09:25:29.273 回答
0

Windows 需要能够在运行时定位 DLL,而不仅仅是编译时。将 DLL 放在您的二进制文件夹中,或者放在某个位置,PATH静态导入将起作用。

于 2012-07-17T08:33:04.543 回答
0

您的 C# 方法声明与 C++ 不匹配:

long mult(int a, int b) 

private delegate int Multiply(int a, int b);

尝试将返回类型更改为 long?

于 2012-07-17T10:11:52.067 回答