对 DLL 入口点感到困惑(未找到入口点异常) [英] Confused over DLL entry points (entry point not found exception)

查看:41
本文介绍了对 DLL 入口点感到困惑(未找到入口点异常)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习如何在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆