动态和静态地将非托管C ++ DLL导入C#不起作用

时间:2012-07-17 08:19:02

标签: c# c++ dllimport

我正在尝试将用非托管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. 当我使用带有32位DLL文件的DLLWrapper类时,我得到“DLLNotFoundException”,但DLL文件正好在该路径中。
  2. 当我将DLLWrapper类与64位DLL文件一起使用并将“Platform Target”属性更改为“x64”时,我得到相同的“DLLNotFoundException”,如果我尝试使用“x86”构建,那么我得到“BadImageException”
  3. 当我使用DynamicDLLImport类时,我总是在代码中注明“HERE ARGUMENTNULLEXCEPTION”的行中得到“ArgumentNullException”。
  4. 我做错了什么?

4 个答案:

答案 0 :(得分:1)

你是如何从DLL导出函数的? Windows DLL不会自动导出所有函数,并且C ++会修饰名称,例如分隔函数重载,例如,除非你告诉它不要,但确切地说编译器是如何特定的,而其他语言肯定不理解它。

您可以通过启动visual studio命令提示符并使用命令

进行检查
dumpbin /EXPORTS "your library.dll"

答案 1 :(得分:1)

问题原来是dll是以调试模式部署的,而不是以正确的方式部署。当它在发布模式下部署时,一切似乎都运行正常。任何有类似问题的人都应该知道在调试模式下编译dll并将其复制到另一台计算机上并不是正确的方法。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

long mult(int a, int b) 

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

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