c# - 对 DLL 入口点感到困惑(入口点未找到异常)

标签 c# c++ visual-studio-2010 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);

...

也许我误解了调用约定。任何帮助将不胜感激。谢谢。

最佳答案

使用

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 不会发出正确的代码以将参数压入堆栈

关于c# - 对 DLL 入口点感到困惑(入口点未找到异常),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7276389/

相关文章:

c++ - Unresolved external symbol 问题

c++ - 使用 Armadillo 库进行意外(错误)的模板推导

c++ - 为指针分配地址

c++ - 提取头文件中的函数列表

c# - 数据库未显示在 Visual Studio 中

c# - 使用预处理器指令 #if 在 Visual Studio 中调试 WindowsService

c# - 使用 RxCpp 构建 Observer/Observable 模式

c# - 改进正则表达式以将大文本拆分为句子

c# - UserManager.CreateAsync 不会在 ApplicationUser 中保存添加的属性

c# - Marshal.StructureToPtr 在模块 ntdll.dll 中失败