gpt4 book ai didi

winapi - 使用 dllexport 从 DLL 导出函数

转载 作者:行者123 更新时间:2023-12-02 13:00:51 27 4
gpt4 key购买 nike

我想要一个从 C++ Windows DLL 导出函数的简单示例。

我想查看 header 、.cpp 文件和 .def 文件(如果绝对需要)。

我希望导出的名称未修饰。我想使用最标准的调用约定(__stdcall?)。我想使用 __declspec(dllexport) 而不必使用 .def 文件。

例如:

  //header
extern "C"
{
__declspec(dllexport) int __stdcall foo(long bar);
}

//cpp
int __stdcall foo(long bar)
{
return 0;
}

我试图避免链接器在名称中添加下划线和/或数字(字节数?)。

我可以不支持使用相同 header 的 dllimportdllexport。我不需要任何有关导出 C++ 类方法的信息,只需要 C 风格的全局函数。

更新

不包括调用约定(并使用 extern "C")为我提供了我喜欢的导出名称,但这意味着什么?我得到的默认调用约定是 pinvoke (.NET)、声明 (vb6) 和 GetProcAddress 所期望的吗? (我猜对于 GetProcAddress 来说,它将取决于调用者创建的函数指针)。

我希望在没有头文件的情况下使用此 DLL,因此我实际上不需要大量花哨的 #defines 来使调用者可以使用该 header 。

我可以接受的答案是我必须使用 *.def 文件。

最佳答案

如果您想要纯 C 导出,请使用 C 项目而不是 C++。 C++ DLL 依赖于所有 C++ 体系(命名空间等)的名称修改。您可以通过进入 C/C++->Advanced 下的项目设置将代码编译为 C,其中有一个选项“Compile As”,它对应于编译器开关/TP 和/TC。

如果您仍然想使用 C++ 编写 lib 的内部结构,但导出一些未损坏的函数以便在 C++ 外部使用,请参阅下面的第二部分。

在 VC++ 中导出/导入 DLL 库

您真正想要做的是在 header 中定义一个条件宏,该 header 将包含在 DLL 项目中的所有源文件中:

#ifdef LIBRARY_EXPORTS
# define LIBRARY_API __declspec(dllexport)
#else
# define LIBRARY_API __declspec(dllimport)
#endif

然后在要导出的函数上使用LIBRARY_API:

LIBRARY_API int GetCoolInteger();

在您的库构建项目中创建一个定义LIBRARY_EXPORTS,这将导致您的函数被导出以用于您的 DLL 构建。

由于 LIBRARY_EXPORTS 不会在使用 DLL 的项目中定义,因此当该项目包含库的头文件时,所有函数都将被导入。

如果您的库是跨平台的,您可以在不在 Windows 上时将 LIBRARY_API 定义为空:

#ifdef _WIN32
# ifdef LIBRARY_EXPORTS
# define LIBRARY_API __declspec(dllexport)
# else
# define LIBRARY_API __declspec(dllimport)
# endif
#elif
# define LIBRARY_API
#endif

使用 dllexport/dllimport 时,不需要使用 DEF 文件,如果使用 DEF 文件,则不需要使用 dllexport/dllimport。这两种方法以不同的方式完成相同的任务,我相信 dllexport/dllimport 是这两种方法中推荐的方法。

从 LoadLibrary/PInvoke 的 C++ DLL 导出未损坏的函数

如果您需要使用 LoadLibrary 和 GetProcAddress,或者可能从其他语言导入(即来自 .NET 的 PInvoke,或 Python/R 中的 FFI 等),您可以使用 extern "C" 内联您的 dllexport 告诉 C++ 编译器不要破坏名称。由于我们使用 GetProcAddress 而不是 dllimport,因此我们不需要从上面进行 ifdef 舞蹈,只需一个简单的 dllexport:

代码:

#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)

EXTERN_DLL_EXPORT int getEngineVersion() {
return 1;
}

EXTERN_DLL_EXPORT void registerPlugin(Kernel &K) {
K.getGraphicsServer().addGraphicsDriver(
auto_ptr<GraphicsServer::GraphicsDriver>(new OpenGLGraphicsDriver())
);
}

这是使用 Dumpbin/exports 导出的内容:

  Dump of file opengl_plugin.dll

File Type: DLL

Section contains the following exports for opengl_plugin.dll

00000000 characteristics
49866068 time date stamp Sun Feb 01 19:54:32 2009
0.00 version
1 ordinal base
2 number of functions
2 number of names

ordinal hint RVA name

1 0 0001110E getEngineVersion = @ILT+265(_getEngineVersion)
2 1 00011028 registerPlugin = @ILT+35(_registerPlugin)

所以这段代码工作正常:

m_hDLL = ::LoadLibrary(T"opengl_plugin.dll");

m_pfnGetEngineVersion = reinterpret_cast<fnGetEngineVersion *>(
::GetProcAddress(m_hDLL, "getEngineVersion")
);
m_pfnRegisterPlugin = reinterpret_cast<fnRegisterPlugin *>(
::GetProcAddress(m_hDLL, "registerPlugin")
);

关于winapi - 使用 dllexport 从 DLL 导出函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/538134/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com