将已经作为独立可执行文件开发的C++项目转换为DLL

6

(我正在使用安装在Windows 7 64位机器上的Microsoft Visual Studio 2010)

我开发了一个C++程序,更像是一个库,随着时间的推移变得相当复杂。目前它可以作为一个简单可执行文件运行,但我想将其转换成DLL,这样其他程序就可以轻松地访问其功能。

我对使用DLL没有任何经验,但我希望在过程中避免大量额外的工作和代码更改。

我知道可以选择编译目标为“DLL”,但我感觉仅靠这一点是不够的。

  • 如果我成功将我的项目编译为一个DLL文件,如何从一个可执行项目中使用其中的函数?

  • 我能否避免使用_dllexport并按名称导入每个函数?

  • 如何静态链接DLL,这样做的(不利)优点是什么?


你不会静态链接 DLL:DLL 的定义就是它们是在运行时动态链接的库。 - Lightness Races in Orbit
首先,感谢您建设性和尊重的回复:') 其次,似乎有一种方法可以在链接器中使用.lib文件进行地址解析,但仍然可以在运行时使用DLL。 - lamas
当您将项目构建为DLL时,IDE将生成用于运行时的DLL文件和包含导出函数解析信息的LIB文件,这就是您要链接的文件。 - Steve Townsend
1
C++ + DLL == 痛苦!(C++接口在DLL之间无法干净地工作...通常最好从DLL中公开一个C接口,以确保您不会意外破坏ODR) - Billy ONeal
4个回答

3
说实话,我建议您查看DLL导出文档,并选择最适合您的导出方法。无论如何,您可以像静态库一样通过名称引用客户端应用程序中的导出函数。
当您将项目构建为DLL时,IDE将生成:
  1. 运行时DLL文件
  2. 包含导出函数解析信息的LIB文件 - 这是您要链接的文件。
根据定义,您不能静态链接DLL(即动态链接库)- 相反,您需要链接到一个库,该库从DLL导出函数,然后DLL在运行时加载,可以在进程启动时自动加载,也可以按需加载整个DLL(请参见LoadLibraryEx等)。

2

由于您正在使用C ++,我假设您正在导出类(?)。CodeProject上有一个非常好的示例,介绍了一些选项。最干净的方法是使用抽象接口:

C ++抽象接口(即只包含纯虚拟方法和没有数据成员的C ++类)尝试获取两全其美的优点:对象的编译器无关的清洁接口和方便的面向对象的方法调用方式。所需的所有操作仅是提供一个带有接口声明的头文件并实现一个工厂函数,该工厂函数将返回新创建的对象实例。只有工厂函数需要使用__declspec(dllexport / dllimport)指定符进行声明。接口不需要任何其他指定符。

如何使用抽象接口示例

您无法静态链接到动态链接库。如果要静态链接,请创建一个.lib。


1
  • 要使用您的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的链接以获取更多信息。

-5

切换到MinGW下的gcc。构建并链接DLL就像构建和链接静态库一样容易。它甚至可以透明地处理C ++名称重整(但是调用程序也需要使用gcc编译)。


3
GCC能够这样做很好,但由于工作环境的限制,这可能不可行。另外,更换编译器可能需要更多的工作量,而将构建类型从.EXE更改为.DLL可能比更换编译器要容易得多。 - Steve Townsend
1
@TonyK:-1。下次你问关于MinGW的问题时,我建议你应该转向使用Visual C++ - 你觉得怎么样? - Doc Brown
@文档:真是个非同寻常的爆发!我只是想要帮忙。 - TonyK
2
@TonyK:“当现有工具可以足够胜任工作时,切换到(插入其他完整的工具集)”并不是对那些只想完成任务的人很有帮助。 - cHao
1
@TonyK:我只是在反思你对楼主说的话 - 也许你没有完全意识到你的回答可能会给其他人留下什么样的印象。 - Doc Brown

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接