c++ VisualStudio中dllimport的使用案例

qvk1mo1f  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(128)

我一直想知道__declspec(dllimport)的真实的用例是什么。我知道构建一个共享库需要使用__declspec(dllexport)导出它的符号,然后库的用户使用这些符号作为__declspec(dllimport)
然后,您应该使用启用dllexport的特殊定义来构建共享库,如果未设置标志,则将符号定义为dllimport
然而,我从来没有使用过dllimport在所有和它只是工作。
我有两个项目:

进出口

有一个小的Util类,它是用定义的EXPORTING构建的
使用时间:

#ifndef _UTIL_H_
#define _UTIL_H_

#if defined(EXPORTING)
#  define EXPORT    __declspec(dllexport)
#else
#  define EXPORT    // I should use __declspec(dllimport) but client will try out
#endif

class EXPORT Util {
public:
    static void test();
};

#endif // !_UTIL_H_

字符串
然后在源文件Util.cpp中:

#include <iostream>

#include "Util.h"

void Util::test()
{
    std::cout << "Testing..." << std::endl;
}


没什么复杂的,正如你所看到的,当用户使用这个文件时,EXPORT根本不会被定义(应该定义为dllimport)。

客户端exe

Main.cpp:

#include <Util.h>

int main(void)
{
    Util::test();

    return 0;
}


链接到ImportExport.lib而不需要任何定义集,就可以正常工作。没有未定义的引用。
我想知道为什么dllimport的用例?它是为了向后兼容而存在的吗?
注意:所有代码都在VisualStudio 2012 Express上进行了测试。

kb5ga3dv

kb5ga3dv1#

Raymond Chen在this series中详细描述了dll导入机制;总结起来,dllimport for functions本质上是一种性能优化。
如果你没有将一个函数标记为dllimport,编译器和链接器will treat it as a normal function,使用“静态”函数调用将其解析为导入库中的存根。存根实际上必须从IAT获取导入函数的地址,并在那里执行jmp。(即,它必须以某种方式将编译器生成的直接调用转换为间接调用),因此在这个两步过程中会有一些性能损失。
相反,dllimport从编译阶段就通过IAT告诉编译器it has to generate code for an indirect call。这减少了间接性,并允许编译器缓存(本地到函数)目标函数地址。
注意,as MSDN says,你可以只在函数中省略dllimport;对于数据,它总是必要的,因为没有一种机制可供链接器修改对编译器生成的变量的直接访问。
(all这在“经典”链接器的时代尤其重要;如今,启用了链接时代码生成,所有这些问题都可以通过简单地让链接器完全生成函数调用/数据访问来解决)

相关问题