将迄今为止作为独立可执行文件开发的 C++ 项目转换为 DLL
Posted
技术标签:
【中文标题】将迄今为止作为独立可执行文件开发的 C++ 项目转换为 DLL【英文标题】:Converting a C++ project so far developed as standalone executable into a DLL 【发布时间】:2011-05-10 17:46:09 【问题描述】:(我在 Windows 7 64 位机器上使用 Microsoft Visual Studio 2010)
我开发了一个 C++ 程序,它更像是一个库,随着时间的推移变得相当复杂。它现在可以作为一个简单的可执行文件工作,但我想将其转换为 DLL,以便其他程序可以轻松访问该功能。
我完全没有使用 DLL 的经验,但我想避免在此过程中进行大量额外的工作和代码更改。
我知道我可以将编译目标选择为“DLL”,但我觉得单独做这个工作是不行的。
如果我成功将我的项目编译成 DLL 文件,我如何从可执行项目中使用其中的函数?
我可以避免使用 _dllexport 并按名称导入每个函数吗?
如何静态链接 DLL,这样做有什么(缺点)优点?
【问题讨论】:
您不会静态链接 DLL:DLL 的定义是它们是动态链接库,在运行时链接。 首先,感谢您的建设性和尊重的回应 :') 其次,似乎有一种方法可以使用 .lib 文件为链接器解析地址,但仍然在运行时使用 DLL跨度> 当您将项目构建为 DLL 时,IDE 将生成用于运行时的 DLL 文件和包含导出函数解析信息的 LIB 文件,这就是您链接的对象。 C++ + DLL == OWW! (C++ 接口不能在 DLL 中干净地工作……通常最好从 DLL 公开 C 接口,以确保您不会意外搞砸 ODR) 【参考方案1】:老实说,我会查看DLL export docs 并选择最适合您的导出方法。在任何情况下,您都可以简单地从客户端应用程序中按名称引用导出的函数,就像使用静态库一样。
当您将项目构建为 DLL 时,IDE 将生成
-
运行时的 DLL 文件和
包含导出的函数解析信息的 LIB 文件 - 就是您链接的那个文件。
根据定义,您不能静态链接 DLL(即 DYNAMIC 链接库) - 相反,您链接到从 DLL 导出函数的库,然后在运行时加载 DLL,或者自动在过程开始或按需。也可以完全按需加载 DLL 而无需任何静态链接(参见LoadLibraryEx 等)。
【讨论】:
【参考方案2】:由于您使用的是 C++,我假设您正在导出类(?)。 CodeProject 上有a really good example,它会引导您完成一些选项。其中最干净的是使用抽象接口:
C++ 抽象接口(即,仅包含纯虚方法且不包含数据成员的 C++ 类)试图获得两全其美:独立于编译器的对象的干净接口,以及方便的面向对象的方法方式来电。所需要做的就是提供一个带有接口声明的头文件并实现一个工厂函数,该函数将返回新创建的对象实例。只有工厂函数必须使用 __declspec(dllexport/dllimport) 说明符声明。该接口不需要任何额外的说明符。
您不能静态链接到动态链接库。如果您想静态链接,请创建一个 .lib。
【讨论】:
【参考方案3】:要使用您的 DLL,您必须#include 与您的 dll/lib 关联的头文件并链接到与您的 .dll 关联的 .lib 文件
您需要 _declspec(dllexport)/_declspec(dllimport) 来指示您要导出/导入 dll 的内容。这可以通过以下方式轻松完成
#ifdef FOO_EXPORTS #define EXPORT_ME __declspec(dllexport) #else #define IMPORT_ME __declspec(dllimport) #endif
在您的 dll 的标题中,您只需 #define FOO_EXPORTS 并放置 EXPORT
foo.hpp
class EXPORT_ME foo2();
void EXPORT_ME foo_funct(foo2 *foo_ptr);
任何需要使用导出项的文件只需要调用 foo.hpp 头中定义的方法(默认行为是导入)
use_foo.cpp
main()
#include "foo.cpp";
foo2 myfoo;
foo_funct(&my_foo);
正如其他人所说,lib 是静态链接的,而 dll 是动态链接的。静态链接时的任何引用元素在编译时被内嵌到源代码中,通常会生成更大的程序(就文件大小而言),而动态链接的元素在运行时链接,因此文件大小通常更小。静态与动态还有许多其他优点/缺点 - 我建议您关注 Doc Browns 链接以获取更多信息
【讨论】:
【参考方案4】:在MinGW下切换到gcc。构建和链接到 DLL 就像构建和链接到静态库一样简单。它甚至可以透明地处理 C++ 名称修改(但调用程序也需要使用 gcc 编译)。
【讨论】:
GCC 这样做很好,但由于工作环境的限制,这可能不可行。此外,切换编译器可能比将构建类型从 EXE 更改为 DLL 需要更多的工作。 @TonyK:-1。下次当你问有关 MinGW 的问题时,我会建议你切换到 Visual C++ - 你会怎么想? @Doc:多么非凡的爆发!我试图提供帮助。 @TonyK:“切换到(插入整个其他工具集)”,当当前的东西可以充分完成工作时,对于只想完成工作的人来说并不是很有帮助。 @TonyK:我只是反映了你告诉 OP 的内容 - 也许你没有完全意识到你的答案可能会出现在其他人面前。以上是关于将迄今为止作为独立可执行文件开发的 C++ 项目转换为 DLL的主要内容,如果未能解决你的问题,请参考以下文章