简体   繁体   English

困惑的DLL入口点(入口点未找到异常)

[英]Confused over DLL entry points (entry point not found exception)

I'm trying to learn how to use DLL's in C#. 我正在尝试学习如何在C#中使用DLL。 I have a very simple DLL just to test the basics. 我有一个非常简单的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());
                }
             }
         }
}

And the DLL code: 和DLL代码:

// TestDLL.cpp

__declspec(dllexport) int __stdcall Add(int a, int b) {
return(a + b);
}

dumpbin returns the following: dumpbin返回以下内容:

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. 也许我不明白DllMain如何作为DLL的C#入口点。 TestDLL.dll works when I test it in a C++ application. TestDLL.dll在我在C ++应用程序中测试时有效。

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 这从dumpbin得到了这个

ordinal   hint   RVA        name
      1      0   00011005   _Add@8 = @ILT+135(_Add@8)

Thus, I changed my C# code: 因此,我改变了我的C#代码:

 // 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 : 我也试过__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 . extern "C"将防止使用params和返回类型进行名称修改,例如?Add@@YGHHH@Z __stdcall will prepend an _ and add @8 : _Add@8 (where 8 is the total size of arguments). __stdcall将添加_并添加@8_Add@8 (其中8是参数的总大小)。 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. DLLImport语句中,由于指定了CallingConvention.StdCall ,因此不需要指定名称mangling。 Just give the regular name ( Add ) and .NET will take care of name mangling ( _Add@8 ). 只需给出常规名称( Add ),.NET将处理名称修改( _Add@8 )。

Note that you must specify the CallingConvention or .NET wouldn't emit the correct code to push arguments on the stack 请注意,您必须指定CallingConvention或.NET不会发出正确的代码来推送堆栈上的参数

For future reference: I had a similar problem, solved creating an EMPTY C++ dll project. 供将来参考:我有类似的问题,解决了创建EMPTY C ++ DLL项目的问题。 Probably the standard Visual Studio template causes some trouble. 可能标准的Visual Studio模板会导致一些麻烦。

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

The following should work. 以下应该有效。

Unmanged: Unmanged:

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

Managed: 管理:

class Program
{
    [DllImport("TestDLL.dll")]
    public static extern int Add(int a, int b);

    static void Main()
    {
        Console.WriteLine(Add(1, 2));
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM