混淆DLL入口点(入口点未找到异常) [英] Confused over DLL entry points (entry point not found exception)
问题描述
我想学习如何在C#中使用DLL。我有一个非常简单的DLL只是为了测试的基础。
// MainForm.cs
b $ b使用系统;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
使用System.Runtime.InteropServices;
命名空间DLL_Test
{
public partial class Form1:Form
{
[DllImport(TestDLL.dll,
EntryPoint = ?添加@@ 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 a,int b){
return(a + b);
}
dumpbin返回以下内容:
$ b b
顺序提示RVA名称
1 0 00011005?Add @@ YGHHH @ Z = @ ILT + 0(?Add @@ YGHHH @ Z)
此(以及下面列出的其他尝试)都返回相同的异常:
System.EntryPointException:找不到名为...的入口点
所以我是如何解决这个问题的损失。也许我不明白DllMain如何作为DLL的C#入口点。
搜索帮助后,我尝试了以下更改:
// TestDLL.cpp
externC__declspec(dllexport)int __stdcall Add(int a,int b){
return(a + b);
}
这将导致dumpbin
顺序提示RVA名称
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
externC __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);
...
也许我误解了调用约定。任何帮助将非常感激。谢谢。
使用
externC__declspec(dllexport)int __stdcall Add(int a,int b){...}
和
[DllImport(TestDLL.dll,CallingConvention = CallingConvention.Stdcall)]
public static extern int Add(int a,int b);
externC
与参数和返回类型如?添加@@ YGHHH @ Z
。
__stdcall将在前面添加 _
并添加 @ 8
: _Add @ / code>(其中8是参数的总大小)。注意,它也影响参数在堆栈上的推送方式。
在 DLLImport
语句中, CallingConvention.StdCall
,您不需要指定名称mangling。只需给出常规名称( Add
),.NET将负责名称调整( _Add @ 8
)。 / p>
请注意,您必须指定CallingConvention或.NET不会发出正确的代码来在堆栈中推送参数
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() + "\n");
}
catch (DllNotFoundException ex)
{
MessageBox.Show(ex.ToString());
}
catch (EntryPointNotFoundException ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
And the DLL code:
// TestDLL.cpp
__declspec(dllexport) int __stdcall Add(int a, int b) {
return(a + b);
}
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 "..."
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);
}
Which results in this from dumpbin
ordinal hint RVA name
1 0 00011005 _Add@8 = @ILT+135(_Add@8)
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);
...
I've also tried __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.
use
extern "C" __declspec(dllexport) int __stdcall Add(int a, int b) { ... }
and
[DllImport("TestDLL.dll", CallingConvention = CallingConvention.Stdcall)]
public static extern int Add(int a, int b);
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.
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
).
Note that you must specify the CallingConvention or .NET wouldn't emit the correct code to push arguments on the stack
这篇关于混淆DLL入口点(入口点未找到异常)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!