对DLL入口点感到困惑(入口点未发现异常)



我正在学习如何在c#中使用DLL。我有一个非常简单的DLL,只是为了测试基础。

// MainForm.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace DLL_Test
{
        public partial class Form1 : Form
        {
            [DllImport("TestDLL.dll",
                        EntryPoint="?Add@@YGHHH@Z",
                        ExactSpelling = true,
                        CallingConvention = CallingConvention.StdCall)]
            public static extern int Add(int a, int b);
            public Form1()
            {
                InitializeComponent();
            }
            private void button1_Click(object sender, EventArgs e)
            {
                int num;
                try
                {
                    num = Add(2, 3);
                    richTextBox1.AppendText(num.ToString() + "n");
                }
                catch (DllNotFoundException ex)
                {
                    MessageBox.Show(ex.ToString());
                }
                catch (EntryPointNotFoundException ex)
                {
                    MessageBox.Show(ex.ToString());
                }
             }
         }
}

和DLL代码:

// TestDLL.cpp
__declspec(dllexport) int __stdcall Add(int a, int b) {
return(a + b);
}

dumpbin返回以下内容:

ordinal   hint   RVA        name
      1      0   00011005   ?Add@@YGHHH@Z = @ILT+0(?Add@@YGHHH@Z)

这个(和下面列出的其他尝试)都返回了相同的异常:

System.EntryPointException: Unable to find entry point named "..."

所以我不知道如何解决这个问题。也许我不明白DllMain是如何作为DLL的c#入口点的。当我在c++应用程序中测试TestDLL.dll时,它可以工作。

在寻求帮助后,我尝试了以下更改:

// TestDLL.cpp
extern "C" __declspec(dllexport) int __stdcall Add(int a, int b) {
return(a + b);
}

这导致从dumpbin

ordinal   hint   RVA        name
      1      0   00011005   _Add@8 = @ILT+135(_Add@8)
因此,我改变了我的c#代码:
 // MainForm.cs
...
[DllImport("TestDLL.dll",
                        EntryPoint="_Add",
                        ExactSpelling = true,
                        CallingConvention = CallingConvention.StdCall)]
            public static extern int Add(int a, int b);
...

我也试过__cdecl:

// TestDLL.cpp
extern "C" __declspec(dllexport) int __cdecl Add(int a, int b) {
return(a + b);
}

.

// MainForm.cs
...
[DllImport("TestDLL.dll",
                        EntryPoint="_Add",
                        ExactSpelling = true,
                        CallingConvention = CallingConvention.Cdecl)]
            public static extern int Add(int a, int b);
...

也许我误解了呼叫约定。任何帮助都将非常感激。谢谢你。

use

extern "C" __declspec(dllexport) int __stdcall Add(int a, int b) { ... }

[DllImport("TestDLL.dll", CallingConvention = CallingConvention.Stdcall)] 
public static extern int Add(int a, int b); 

extern "C"将防止参数和返回类型(如?Add@@YGHHH@Z)的名称混淆。__stdcall将在_前面加上@8: _Add@8(其中8是参数的总大小)。注意,它还会影响参数在堆栈上的压入方式。

DLLImport语句中,既然指定了CallingConvention.StdCall,就不需要指定名称混淆。只要给出常规名称(Add), . net就会处理名称混淆(_Add@8)。

注意必须指定CallingConvention,否则。net不会发出正确的代码来将参数压入堆栈

下面应该可以工作。

Unmanged:

extern "C" __declspec(dllexport) int Add(int a, int b) 
{
    return(a + b);
}
管理:

class Program
{
    [DllImport("TestDLL.dll")]
    public static extern int Add(int a, int b);
    static void Main()
    {
        Console.WriteLine(Add(1, 2));
    }
}

供将来参考:我有一个类似的问题,解决了创建一个空的c++ dll项目。可能是标准的Visual Studio模板造成了一些麻烦。

参考此链接:http://www.codeproject.com/Articles/9826/How-to-create-a-DLL-library-in-C-and-then-use-it-w

相关内容

最新更新