关于c++动态库的dllexport和dllimport

先推荐一款比Microsoft Coplilot更好用的辅助编程工具——Cursor, 一款基于GPT4的新一代辅助编程神器——Cursor,官网介绍说是与OpenAI合作并且基于GPT4。自己体验了下,确实不错,值得尝试。

官网地址:

Cursor | Build Fast

关于动态库的dllexport和dllimport关键字的使用。什么时候用dllexport,什么时候用dllimport。

dllexport和dllimport

是用于在动态链接库(DLL)中导出和导入函数和数据的关键字。在Windows操作系统中,动态链接库是一种可重定位的二进制文件,其中包含可由多个应用程序共享的代码和数据。使用动态链接库可以减小可执行文件的大小,同时也可以提高代码的重用性和可维护性。

dllexport

用于将函数或数据导出到DLL中,以便其他应用程序可以使用它们。例如,如果您编写了一个名为

MyFunction的函数,并将其标记为dllexport,则其他应用程序可以使用LoadLibrary和GetProcAddress函数来加载和调用该函数。

dllimport

用于从DLL中导入函数或数据,以便您的应用程序可以使用它们。例如,如果您想在您的应用程序中使用另一个DLL中的函数,则可以将该函数标记为dllimport,并在您的代码中使用它。

在使用dllexport和dllimport时,需要注意以下几点:

  • dllexport和dllimport只能用于Windows操作系统。

  • dllexport和dllimport只能用于动态链接库(DLL)中。

  • dllexport和dllimport只能用于导出和导入函数和数据。

  • dllexport和dllimport的语法相同,只是用法不同。

  • dllexport和dllimport都需要指定函数或数据的名称和可见性。

  • dllexport和dllimport都可以指定函数或数据的调用约定。

  • dllexport和dllimport都可以指定函数或数据的存储类别。

dllexport生成的lib文件既可以是静态库,也可以是导入库(import library)。生成的.lib文件包含了导出函数的信息,以及用于在链接时解析函数地址的信息。如果您将导出函数标记为dllexport,则编译器将生成一个.lib文件,其中包含了导出函数的信息。如果您将导入函数标记为dllimport,则编译器将生成一个.lib文件,其中包含了导入函数的信息。

.lib文件的作用是在链接时解析函数地址。当您编写一个应用程序并调用一个动态链接库中的函数时,编译器不知道该函数的地址在哪里。因此,编译器会生成一个包含函数名称的符号表,并将其保存在.obj文件中。当您链接应用程序时,链接器将查找符号表中的函数名称,并将其替换为函数的地址。如果您使用的是静态链接库,则链接器将直接将函数的代码复制到应用程序中。如果您使用的是导入库,则链接器将在运行时从DLL中加载函数。

要使用.lib文件,您需要将其包含在链接器命令行中。例如,如果您有一个名为MyLibrary的DLL,并且您想在应用程序中使用其中的函数,则可以使用以下命令行:

其中,/I选项用于指定头文件的搜索路径,/link选项用于指定链接器,/LIBPATH选项用于指定

.lib文件的搜索路径,MyApplication.cpp是您的应用程序源文件,MyLibrary.lib是您的DLL的导入库。

.lib 文件一定是静态库吗?

非也,像前面介绍的,.lib文件都是用作动态库的链接使用的。

在Windows平台上, .lib 文件可以是静态库文件,也可以是用于链接的库文件。以下是一些区分它们的方法:

1. 查看文件大小:通常情况下,静态库文件的大小会比较大,因为它们包含了实际的目标代码。而用于链接的库文件的大小较小,因为它们只包含了用于在编译时引用动态库的符号信息。

2. 查看导出符号:可以使用工具(如 dumpbin )查看 .lib 文件中的导出符号。静态库文件通常会包含大量的导出符号,因为它们包含了实际的目标代码。而用于链接的库文件可能只包含少量的导出符号,因为它们只提供了动态库的接口。

3. 查看文件依赖:可以使用工具(如 Dependency Walker )查看 .lib 文件的依赖关系。如果 .lib 文件依赖于其他 .lib 文件,那么它很可能是一个静态库文件。而如果 .lib 文件依赖于动态链接库( .dll 文件),那么它可能是用于链接的库文件。

最简单的区分方法:一看大小,二,使用压缩软件打开直接查看。看到的内容里面是dll的,不用说这种必定的动态库的链接文件,不是静态库文件。如果lib文件打不开或者很大,或者打开的内容是类似OBJ后缀,则是静态文件。

Q_DECL_IMPORT和Q_DECL_EXPORT

是Qt中的两个宏定义,用于在不同的平台上实现动态链接库的导入和导出。在Windows平台上,动态链接库的导入和导出需要使用__declspec(dllexport)和__declspec(dllimport)关键字,而在Linux平台上则需要使用__attribute__((visibility("default")))关键字。

为了方便跨平台开发,Qt定义了Q_DECL_IMPORT和Q_DECL_EXPORT宏,它们在不同的平台上会被定义为不同的关键字,从而实现了跨平台的动态链接库导入和导出。

Q_DECL_IMPORT

用于声明一个动态链接库的导入函数或变量,它通常用于头文件中。在Windows平台上,Q_DECL_IMPORT会被定义为__declspec(dllimport),在Linux平台上则会被定义为一个空宏。使用Q_DECL_IMPORT可以使得头文件中的函数和变量在不同的平台上都能正确地导入。

Q_DECL_EXPORT

用于声明一个动态链接库的导出函数或变量,它通常用于源文件中。在Windows平台上,Q_DECL_EXPORT会被定义为__declspec(dllexport),在Linux平台上则会被定义为__attribute__((visibility("default")))。

使用Q_DECL_EXPORT可以使得源文件中的函数和变量在不同的平台上都能正确地导出。

dll动态库没有提供lib文件,如何使用?

如果提供的同时有dll库和对应的lib文件,则动态库的使用很简单,编译器可以在链接时给你全局载入。如果你只有一个DLL文件,而没有LIB文件,那么你可以使用LoadLibrary函数来加载DLL文件并获取函数指针。这种方法被称为动态链接。以下是一个示例:

#include <windows.h>
#include <iostream>

typedef int (*MYPROC)(int);

int main() {
    HINSTANCE hinstLib;
    MYPROC ProcAdd;

    hinstLib = LoadLibrary(TEXT("MyDll.dll"));
    if (hinstLib != NULL) {
        ProcAdd = (MYPROC)GetProcAddress(hinstLib, "MyFunction");
        if (ProcAdd != NULL) {
            int result = ProcAdd(1);
            std::cout << "Result: " << result << std::endl;
        } else {
            std::cout << "Could not find function" << std::endl;
        }
        FreeLibrary(hinstLib);
    } else {
        std::cout << "Could not load library" << std::endl;
    }

    return 0;
}

在这个例子中,我们使用LoadLibrary函数来加载MyDll.dll文件。然后,我们使用GetProcAddress函数来获取MyFunction函数的地址。最后,我们将函数指针转换为MYPROC类型,并调用它来执行函数。

参考文献:

Cursor | Build Fast

比Microsoft Coplilot更好用的辅助编程工具——Cursor - 掘金

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

特立独行的猫a

您的鼓励是我的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值