31

我正在尝试创建一个导出名为“GetName”的函数的 DLL。我希望其他代码能够调用此函数而不必知道损坏的函数名称。

我的头文件如下所示:

#ifdef __cplusplus
#define EXPORT extern "C" __declspec (dllexport)
#else
#define EXPORT __declspec (dllexport)
#endif

EXPORT TCHAR * CALLBACK GetName();

我的代码如下所示:

#include <windows.h>
#include "PluginOne.h"

int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
{
     return TRUE ;
}

EXPORT TCHAR * CALLBACK GetName()
{
    return TEXT("Test Name");
}

当我构建时,DLL 仍然导出名称为:“_GetName@0”的函数。

我究竟做错了什么?

4

4 回答 4

27

小更正-通过clinet成功解析名称

extern "C"

必须在出口方和进口方一样。

extern "C" 将 proc 的名称简化为:"_GetName"。

此外,您可以在 .def 文件中的 EXPORTS 部分的帮助下强制使用任何名称

于 2009-09-23T16:35:22.807 回答
9

这对于具有__stdcall约定的 DLL 导出是正常的。@N 指示函数在其参数中采用的字节数-在您的情况下为零。

请注意,有关从 DLL 导出的 MSDN 页面明确指出,在使用“函数定义中的关键字 __declspec(dllexport)”时“使用 __stdcall 调用约定”。

于 2009-09-23T16:35:32.977 回答
7

正确答案如下:

extern "C" int MyFunc(int param);

int MyFunc(int param);

是两个使用不同内部命名的声明,第一个是 C 风格,第二个是 C++ 风格。

构建工具需要内部命名来确定函数接收哪些参数、返回什么类型等,因为 C++ 更复杂(oop、重载、虚函数等)——它使用更复杂的命名。调用约定也会影响 c 和 c++ 命名。

当以相同的方式使用 __declspec(dllexport) 时,会应用这两种命名方式。

如果您想省略导出例程的名称修改,请将模块定义文件添加到您的项目中,输入它(在这种情况下,您不需要 declspec dllexport):

LIBRARY mylib
EXPORTS
  MyFunc

这将省略显式名称装饰(下面的示例)。

_MyFunc (c style, __cdecl)
_MyFunc@4 (c style, __stdcall)
?MyFunc@@YAHH@Z (c++ style, __cdecl)
?MyFunc@@YGHH@Z (c++ style, __stdcall)
于 2013-06-29T18:29:40.670 回答
4

您可以使用“-Wl,--kill-at”链接器开关来禁用名称修改。

例如,在 Code::Blocks 中,在自定义链接器设置中,添加:-Wl,--kill-at

于 2014-02-12T00:11:25.867 回答