我正在学习如何在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);
...
也许我误解了呼叫约定。任何帮助都将非常感激。谢谢你。
use
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是参数的总大小)。注意,它还会影响参数在堆栈上的压入方式。
在DLLImport
语句中,既然指定了CallingConvention.StdCall
,就不需要指定名称混淆。只要给出常规名称(Add
), . net就会处理名称混淆(_Add@8
)。
注意必须指定CallingConvention,否则。net不会发出正确的代码来将参数压入堆栈
下面应该可以工作。
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));
}
}
供将来参考:我有一个类似的问题,解决了创建一个空的c++ dll项目。可能是标准的Visual Studio模板造成了一些麻烦。
参考此链接:http://www.codeproject.com/Articles/9826/How-to-create-a-DLL-library-in-C-and-then-use-it-w