C# 中的 dllimport 使用的 c++ 非托管 dll 产生入口点未找到错误
c++ unmanaged dll used by dllimport in C# produces entry point not found error
我知道这个问题已经在这里问过很多次了。我已经阅读了所有可以找到的问题以及 Whosebug 之外的信息。到目前为止,我还没有找到可以解决我遇到的具体问题的答案。
这里是非托管 c++ dll 头文件的代码。
namespace MyWin32DLL
{
class MyWin32ClassOne
{
public:
static __declspec(dllexport) int Getvar();
};
}
这里是c++ dll cpp文件的代码
#include "MyWin32ClassOne.h"
namespace MyWin32DLL
{
int MyWin32ClassOne::Getvar()
{
return 123;
}
}
这段代码是我从各种来源整理的,所以它可能根本不正确。我对 c++ 或 dll 不是很有经验。
这是我试图访问 dll 的愚蠢的小 c# winforms prog 的代码。 (已编辑以更正 tolanj 在评论中指出的类型不匹配)
namespace TestDll
{
public partial class Form1 : Form
{
[DllImport("MyWin32CppDll.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int Getvar();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string response = Getvar().ToString();
MessageBox.Show(response, "title", MessageBoxButtons.OK);
}
}
}
现在,在这一点上,我明白我很可能会收到 "no entry point" 错误,因为 c++ 编译器如何破坏方法和函数的名称。
据我所知,我可以做两件事来解决这个问题。
事情 1
在我的声明之前添加 extern "c" 这样名称就不会被编译器破坏。
namespace MyWin32DLL
{
class MyWin32ClassOne
{
public:
extern "C" static __declspec(dllexport) int Getvar();
};
}
当我尝试这个时,我从 Visual Studio 得到一个错误,指出 "linkage specification isn't allowed".
好的,所以我尝试了第 2 件事,即使用 dumpbin 查找函数的错位名称,并将错位名称用作 dllimport 调用中的入口点。
所以我 运行 dumpbin /symbols 在我的 dll 上,我没有得到任何函数名称,无论是损坏还是其他。
Dump of file mywin32cppdll.dll
File Type: DLL
Summary
1000 .data
1000 .idata
2000 .rdata
1000 .reloc
1000 .rsrc
4000 .text
10000 .textbss
接下来我尝试 dumpbin /exports
Dump of file mywin32cppdll.dll
File Type: DLL
Section contains the following exports for MyWin32CppDll.dll
00000000 characteristics
554CF7D4 time date stamp Fri May 08 13:52:20 2015
0.00 version
1 ordinal base
1 number of functions
1 number of names
ordinal hint RVA name
1 0 00011005 ?Getvar@MyWin32ClassOne@MyWin32DLL@@SAHXZ = @ILT+0(?Getvar@MyWin32ClassOne@MyWin32DLL@@SAHXZ)
Summary
1000 .data
1000 .idata
2000 .rdata
1000 .reloc
1000 .rsrc
4000 .text
10000 .textbss
看着那个,我没有看到要使用的损坏或修饰的名称。但是作为一个笨蛋,我使用 "Getvar@MyWin32ClassOne@MyWin32DLL@@SAHXZ" 作为我的入口点,但在我的 C# 程序中仍然出现同样的错误。
显然我错过了一些东西。如何从我的 c# 程序访问 dll 函数?
如您所见,名称已被损坏。您已经设法省略了损坏名称开头的 ?
。您的导入应该是:
[DllImport("MyWin32CppDll.dll", CallingConvention = CallingConvention.Cdecl,
EntryPoint = "?Getvar@MyWin32ClassOne@MyWin32DLL@@SAHXZ")]
public static extern int Getvar();
另请注意,您的函数使用 cdecl 调用约定。
我知道这个问题已经在这里问过很多次了。我已经阅读了所有可以找到的问题以及 Whosebug 之外的信息。到目前为止,我还没有找到可以解决我遇到的具体问题的答案。
这里是非托管 c++ dll 头文件的代码。
namespace MyWin32DLL
{
class MyWin32ClassOne
{
public:
static __declspec(dllexport) int Getvar();
};
}
这里是c++ dll cpp文件的代码
#include "MyWin32ClassOne.h"
namespace MyWin32DLL
{
int MyWin32ClassOne::Getvar()
{
return 123;
}
}
这段代码是我从各种来源整理的,所以它可能根本不正确。我对 c++ 或 dll 不是很有经验。
这是我试图访问 dll 的愚蠢的小 c# winforms prog 的代码。 (已编辑以更正 tolanj 在评论中指出的类型不匹配)
namespace TestDll
{
public partial class Form1 : Form
{
[DllImport("MyWin32CppDll.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int Getvar();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string response = Getvar().ToString();
MessageBox.Show(response, "title", MessageBoxButtons.OK);
}
}
}
现在,在这一点上,我明白我很可能会收到 "no entry point" 错误,因为 c++ 编译器如何破坏方法和函数的名称。
据我所知,我可以做两件事来解决这个问题。
事情 1 在我的声明之前添加 extern "c" 这样名称就不会被编译器破坏。
namespace MyWin32DLL
{
class MyWin32ClassOne
{
public:
extern "C" static __declspec(dllexport) int Getvar();
};
}
当我尝试这个时,我从 Visual Studio 得到一个错误,指出 "linkage specification isn't allowed".
好的,所以我尝试了第 2 件事,即使用 dumpbin 查找函数的错位名称,并将错位名称用作 dllimport 调用中的入口点。
所以我 运行 dumpbin /symbols 在我的 dll 上,我没有得到任何函数名称,无论是损坏还是其他。
Dump of file mywin32cppdll.dll
File Type: DLL
Summary
1000 .data
1000 .idata
2000 .rdata
1000 .reloc
1000 .rsrc
4000 .text
10000 .textbss
接下来我尝试 dumpbin /exports
Dump of file mywin32cppdll.dll
File Type: DLL
Section contains the following exports for MyWin32CppDll.dll
00000000 characteristics
554CF7D4 time date stamp Fri May 08 13:52:20 2015
0.00 version
1 ordinal base
1 number of functions
1 number of names
ordinal hint RVA name
1 0 00011005 ?Getvar@MyWin32ClassOne@MyWin32DLL@@SAHXZ = @ILT+0(?Getvar@MyWin32ClassOne@MyWin32DLL@@SAHXZ)
Summary
1000 .data
1000 .idata
2000 .rdata
1000 .reloc
1000 .rsrc
4000 .text
10000 .textbss
看着那个,我没有看到要使用的损坏或修饰的名称。但是作为一个笨蛋,我使用 "Getvar@MyWin32ClassOne@MyWin32DLL@@SAHXZ" 作为我的入口点,但在我的 C# 程序中仍然出现同样的错误。
显然我错过了一些东西。如何从我的 c# 程序访问 dll 函数?
如您所见,名称已被损坏。您已经设法省略了损坏名称开头的 ?
。您的导入应该是:
[DllImport("MyWin32CppDll.dll", CallingConvention = CallingConvention.Cdecl,
EntryPoint = "?Getvar@MyWin32ClassOne@MyWin32DLL@@SAHXZ")]
public static extern int Getvar();
另请注意,您的函数使用 cdecl 调用约定。