对 DLL 入口点感到困惑(未找到入口点异常) [英] Confused over DLL entry points (entry point not found exception)
问题描述
我正在尝试学习如何在 C# 中使用 DLL.我有一个非常简单的 DLL 只是为了测试基础.
I'm trying to learn how to use DLL's in C#. I have a very simple DLL just to test the basics.
// 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() + "
");
}
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 返回以下内容:
dumpbin returns the following:
ordinal hint RVA name
1 0 00011005 ?Add@@YGHHH@Z = @ILT+0(?Add@@YGHHH@Z)
这(以及下面列出的其他尝试)都返回了相同的异常:
This (and other attempts listed below) have all returned the same exception:
System.EntryPointException: Unable to find entry point named "..."
所以我不知道如何解决这个问题.也许我不明白 DllMain 如何作为 DLL 的 C# 入口点.当我在 C++ 应用程序中测试它时,TestDLL.dll 工作.
So I am at a loss for how to solve this. Perhaps I do not understand how DllMain functions as the C# entry point for a DLL. TestDLL.dll works when I test it in a C++ application.
在寻求帮助后,我尝试了以下更改:
After searching for help, I've attempted the following changes:
// TestDLL.cpp
extern "C" __declspec(dllexport) int __stdcall Add(int a, int b) {
return(a + b);
}
dumpbin 的结果
Which results in this from dumpbin
ordinal hint RVA name
1 0 00011005 _Add@8 = @ILT+135(_Add@8)
因此,我更改了我的 C# 代码:
Thus, I changed my C# code:
// 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);
...
也许我误解了调用约定.任何帮助将不胜感激.谢谢.
Perhaps I'm misunderstanding the calling conventions. Any help would be very appreciated. Thank you.
推荐答案
使用
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 是参数的总大小).请注意,它还会影响参数入栈的方式.
extern "C"
will prevent name mangling with params and return type such as ?Add@@YGHHH@Z
.
__stdcall will prepend an _
and add @8
: _Add@8
(where 8 is the total size of arguments). Note that it also affects the way parameters are pushed on the stack.
在您的 DLLImport
语句中,由于您指定了 CallingConvention.StdCall
,因此您无需指定名称修改.只需提供常规名称 (Add
),.NET 就会处理名称修改 (_Add@8).
In your DLLImport
statement, since you specify CallingConvention.StdCall
, you don't need to specify the name mangling. Just give the regular name (Add
) and .NET will take care of name mangling (_Add@8
).
请注意,您必须指定 CallingConvention 或 .NET 不会发出正确的代码来将参数推送到堆栈上
Note that you must specify the CallingConvention or .NET wouldn't emit the correct code to push arguments on the stack
这篇关于对 DLL 入口点感到困惑(未找到入口点异常)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!