Visual Studio 2015 C++ 将独立的 DLL 文件添加到项目中

visual studio 2015 c++ add a standalone dll file to a project

本文关键字:添加 文件 项目 DLL 2015 Studio C++ 独立 Visual      更新时间:2023-10-16

所以我正在开发一些用于c ++的库,以使初学者的体验更容易。我已经将库放入一个独立的 dll 中,现在我想将其添加到另一个项目中。但问题是在互联网上搜索了很长时间之后,我必须包含目录和东西,但我想要的只是将单个 dll 文件包含在项目中,以便项目可以访问里面的 .h 和.cpp文件。Ik 我可以使用 java 添加外部 jar,然后我可以访问那里的库,但我如何在 Visual Studio 2015 中使用 c++ 做到这一点?

这不是C++的工作方式(我也假设你不是在谈论C++/CX或MC++——严格来说,这些都不C++)

C++语言没有定义"应用程序二进制接口" - 允许二进制文件之间链接的 ABI。这是一个实现问题。

有一些支持C++的 ABI,例如 COM 和 CORBA,事实上最新的是 WinRT - 本身基于 COM。

C++不同于Java和C#等语言,后者要求运行时具有ABI:Java有其.class.jar文件,而.NET/C#在其程序集中包含其CLR元数据(.dll文件 - 与"真正的"DLL文件不同)。

请注意,C# 编译器生成的 DLL 文件与C/C++ 编译器工具链的链接器生成的 DLL 文件完全不同 - 虽然它们与 PE(可移植可执行文件)文件共享通用的外部格式,但它们在内部完全不同:CLR DLL 包含中间字节码 CIL,而"真正的"DLL 包含特定于处理器的本机指令。

在C++ 中使用其他库的一般方法是以源代码形式(作为项目中包含的.c.cpp文件)使用它们,或者作为具有.lib.h头文件(静态库),它们几乎类似于可重用的二进制文件,只是它们被链接("编译到并合并")到完成的二进制文件中,并且无法在运行时替换。

另一种方法是使用动态链接,它需要您的运行时(即 Win32)为您执行运行时链接,通常使用GetProcAddress- 但这仅导出 C 样式函数,而不是整个对象和类(当然也不是任何C++模板)。

总结:

  • 您有一个 DLL,并且想要在其中使用代码:
    • 它是WinRT DLL吗?
      • 如果要使用纯C++则需要使用 WTL。请注意,这种方法不适合胆小的人。
      • 否则,如果你对C++/CX没问题,那么你实际上可以使用Visual Studio中的"添加引用"UI,但请注意,你不再编写"真正的"C++了。
    • 否则它是一个 COM 库吗? (
      • 请注意,您将需要 ATL(活动模板库)和其中包含的类型的 IDL 定义,这是头文件的 COM 等效项)。还可以使用#import和/或使用 IDE 生成调用 COM 所需的实际.h.c文件,而不会造成太多痛苦。但是,如果在以后的COM DLL版本中更改了太多内容,则以后替换COM DLL而不重建程序,则会遇到问题(请参阅"DLL 地狱")。
    • 否则它是传统的本机Win32 PE DLL吗?
      • PE 可执行文件所拥有的只是导出函数及其在 DLL 中的地址位置的列表。
      • 您想要静态链接还是动态链接?
        • 对于动态链接,您需要运行时解析(痛苦但灵活)还是"自动"链接?
          • 对于运行时链接,您只需要.dll文件和.h文件。您需要为要调用的每个函数手动调用GetProcAddress,然后调用它。优点是可以在运行时检测函数是否存在并正常处理链接错误。
          • 对于自动链接,除了.dll.h文件外,还将为您提供一个.lib文件,.lib文件是一个小型静态链接库,其中包含为您执行运行时链接所需的存根和其他代码,而无需手动调用GetProcAddress自己。
        • 对于静态链接,您将没有.dll文件,而是一个.lib文件:称为"静态库"。它里面是一个文件,其中包含离散化的可执行函数 blob,链接器将有效地将其复制+粘贴到已完成的程序中。

你怎么像Java一样做?好吧,你没有。

需要标头才能为编译器提供从您可能要使用的 DLL 导出的函数和其他符号的原型。您甚至可能有多个头文件来逻辑划分 DLL 的代码。由于您不希望在源代码中对这些头文件的路径进行硬编码,因此您需要指定其包含目录的路径作为编译器/构建选项的一部分,从而腾出时间使用相对路径。

通常还需要 LIB 文件,尽管这稍微灵活一些。一般来说,LIB 使事情变得容易得多。它将在编译 DLL 时由链接器生成,并且它包含有助于链接到该 DLL 导出的函数的存根。生成使用 DLL 的应用程序时,您可以在链接器选项中指定此 LIB 文件,然后一切正常。这称为隐式动态链接。它是动态链接,因为你使用的是 DLL,但它是隐式的,因为链接器正在为你处理繁琐的工作。

如果您不想使用 LIB 文件,则需要执行显式动态链接。这仍然是动态链接,因为你仍在使用 DLL,但它是显式的,因为您必须显式编写代码来加载 DLL 模块并获取指向它导出的函数的指针。Microsoft的构建工具提供了各种功能来简化此操作,但它仍然比仅使用 LIB 文件更困难,这是我推荐的,除非您有充分的理由这样做。