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

时间:2011-09-01 20:52:31

标签: 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);

...

也许我误解了召唤惯例。任何帮助将非常感激。谢谢。

3 个答案:

答案 0 :(得分:16)

使用

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"将阻止使用params进行名称修改并返回类型?Add@@YGHHH@Z。 __stdcall将添加_并添加@8_Add@8(其中8是参数的总大小)。请注意,它还会影响参数在堆栈上的推送方式。

DLLImport语句中,由于您指定了CallingConvention.StdCall,因此无需指定名称重整。只需给出常规名称(Add),.NET将处理名称修改(_Add@8)。

请注意,您必须指定CallingConvention或.NET不会发出正确的代码来推送堆栈上的参数

答案 1 :(得分:0)

以下情况应该有效。

Unmanged:

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

托管:

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

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

答案 2 :(得分:0)

供将来参考:我有类似的问题,解决了创建EMPTY C ++ DLL项目的问题。可能标准的Visual Studio模板会造成一些麻烦。

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