头文件中的dllexport

头文件中的dllexport,dll,linker,Dll,Linker,我不明白为什么头文件中需要包含\uu declspec(dllexport)或等效文件。假设我正在写一本图书馆。当然,用户不需要知道或担心符号是否被导出,他们关心的只是函数声明是否存在,并且可能与共享库或静态库本身相链接。那么,为什么所有这些样板文件都不能进入源文件,只在构建时使用呢 我想到的唯一一个用例是,有人正在编写我的库的包装器,并且需要导出我的所有函数,但一般来说情况并非如此——将所有导出内容放在公共标题中真的值得吗?有什么我遗漏的吗?这是链接器的技术限制吗 我这样问是因为我喜欢我的标题

我不明白为什么头文件中需要包含
\uu declspec(dllexport)
或等效文件。假设我正在写一本图书馆。当然,用户不需要知道或担心符号是否被导出,他们关心的只是函数声明是否存在,并且可能与共享库或静态库本身相链接。那么,为什么所有这些样板文件都不能进入源文件,只在构建时使用呢

我想到的唯一一个用例是,有人正在编写我的库的包装器,并且需要导出我的所有函数,但一般来说情况并非如此——将所有导出内容放在公共标题中真的值得吗?有什么我遗漏的吗?这是链接器的技术限制吗


我这样问是因为我喜欢我的标题,并且构建的系统是干净的,而且由于
dllexport
东西通常是根据我们是将库构建为共享库还是静态库来设置/不设置的,我觉得奇怪的是,它最终会出现在公共标题中,因为(据我理解)基本上是一个构建时概念。那么,有人能告诉我我遗漏了什么吗?

我不确定我能不能提供一个很好的答案。我的印象是,它有几个用途:

  • 它加快了DLL的加载速度,特别是在使用大量DLL时(因为要搜索的导出符号较少)
  • 它减少了符号在运行时发生冲突的可能性(因为导出的符号较少)
  • 它允许链接器抱怨未定义的符号(而不仅仅是假设它可能在运行时找到它们)
  • 我确信还有其他原因。我通常用如下方式包装我的API:

    #if defined(MY_LIB_CREATION)
        #define MY_LIB_API __declspec(dllexport)
    #else
        #define MY_LIB_API __declspec(dllimport)
    #endif
    
    然后,我所有的API函数和类都被定义为我的_LIB_API:

    class MY_LIB_API Foo {};
    MY_LIB_API void bar();
    

    然后在项目文件中为实现库的项目定义了我的库创建。

    我不确定我能提供一个很好的答案。我的印象是它有几个用途:

  • 它加快了DLL的加载速度,特别是在使用大量DLL时(因为要搜索的导出符号较少)
  • 它减少了符号在运行时发生冲突的可能性(因为导出的符号较少)
  • 它允许链接器抱怨未定义的符号(而不仅仅是假设它可能在运行时找到它们)
  • 我确信还有其他原因。我通常用如下方式包装我的API:

    #if defined(MY_LIB_CREATION)
        #define MY_LIB_API __declspec(dllexport)
    #else
        #define MY_LIB_API __declspec(dllimport)
    #endif
    
    然后,我所有的API函数和类都被定义为我的_LIB_API:

    class MY_LIB_API Foo {};
    MY_LIB_API void bar();
    
    然后在项目文件中为实现库的项目定义MY_LIB_CREATION