Gre*_*egD 9 c# c++ dll visual-studio-2010
我正在尝试学习如何在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());
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
和DLL代码:
// TestDLL.cpp
__declspec(dllexport) int __stdcall Add(int a, int b) {
return(a + b);
}
Run Code Online (Sandbox Code Playgroud)
dumpbin返回以下内容:
ordinal hint RVA name
1 0 00011005 ?Add@@YGHHH@Z = @ILT+0(?Add@@YGHHH@Z)
Run Code Online (Sandbox Code Playgroud)
这(以及下面列出的其他尝试)都返回了相同的异常:
System.EntryPointException: Unable to find entry point named "..."
Run Code Online (Sandbox Code Playgroud)
所以我对如何解决这个问题感到茫然.也许我不明白DllMain如何作为DLL的C#入口点.TestDLL.dll在我在C++应用程序中测试时有效.
在寻求帮助后,我尝试了以下更改:
// TestDLL.cpp
extern "C" __declspec(dllexport) int __stdcall Add(int a, int b) {
return(a + b);
}
Run Code Online (Sandbox Code Playgroud)
这从dumpbin得到了这个
ordinal hint RVA name
1 0 00011005 _Add@8 = @ILT+135(_Add@8)
Run Code Online (Sandbox Code Playgroud)
因此,我改变了我的C#代码:
// MainForm.cs
...
[DllImport("TestDLL.dll",
EntryPoint="_Add",
ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
public static extern int Add(int a, int b);
...
Run Code Online (Sandbox Code Playgroud)
我也尝试过__cdecl:
// TestDLL.cpp
extern "C" __declspec(dllexport) int __cdecl Add(int a, int b) {
return(a + b);
}
Run Code Online (Sandbox Code Playgroud)
.
// MainForm.cs
...
[DllImport("TestDLL.dll",
EntryPoint="_Add",
ExactSpelling = true,
CallingConvention = CallingConvention.Cdecl)]
public static extern int Add(int a, int b);
...
Run Code Online (Sandbox Code Playgroud)
也许我误解了召唤惯例.任何帮助将非常感激.谢谢.
Ser*_*ier 17
使用
extern "C" __declspec(dllexport) int __stdcall Add(int a, int b) { ... }
Run Code Online (Sandbox Code Playgroud)
和
[DllImport("TestDLL.dll", CallingConvention = CallingConvention.Stdcall)]
public static extern int Add(int a, int b);
Run Code Online (Sandbox Code Playgroud)
extern "C"将使用params和返回类型来阻止名称修改?Add@@YGHHH@Z.__stdcall将_添加前缀并添加@8:( _Add@8其中8是参数的总大小).请注意,它还会影响参数在堆栈上的推送方式.
在您的DLLImport语句中,自指定后CallingConvention.StdCall,您无需指定名称mangling.只需给出常规名称(Add)和.NET将处理名称mangling(_Add@8).
请注意,您必须指定CallingConvention或.NET不会发出正确的代码来推送堆栈上的参数