在Visual Studio中dllimport的用例 [英] Use case of dllimport in VisualStudio

查看:303
本文介绍了在Visual Studio中dllimport的用例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直想知道__declspec(dllimport)的真正用例是什么.我知道构建共享库需要使用__declspec(dllexport)导出其符号,然后该库的用户将这些符号用作__declspec(dllimport).

I always wondered what is the real use case of __declspec(dllimport). I know that building a shared library requires to export its symbols using __declspec(dllexport) and then the user of the library use theses symbols as __declspec(dllimport).

然后,您应该使用支持dllexport的特殊定义来构建共享库,如果未设置该标志,则将符号定义为dllimport.

Then, you should build your shared library with a special define which enables dllexport and if the flag is not set, the symbols are defined as dllimport.

但是,我根本没用过dllimport,而且效果很好.

However, I never used dllimport at all and it just works.

我有两个项目:

导入导出

具有一个小型的Util类,该类是通过定义EXPORTING构建的

Has a small Util class which is build with EXPORTING defined

Util.h:

#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中:

Then in the source file Util.cpp:

#include <iostream>

#include "Util.h"

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

正如您所见,当用户使用此文件时,没有什么复杂的事,根本不会定义EXPORT(应该将其定义为dllimport).

Nothing much complicated, as you can see, when the user will use this file, EXPORT will not be defined at all (where it should be defined to dllimport).

客户端exe

Main.cpp:

#include <Util.h>

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

    return 0;
}

没有任何定义集的链接到ImportExport.lib,就可以使用.没有未定义的引用.

Links to ImportExport.lib without any define set, just works. No undefined reference.

我想知道为什么dllimport的用例是什么?是否存在向后兼容性?

I wonder why is the use case of dllimport? Is it present for backward compatibility?

注意:所提供的所有代码均已在VisualStudio 2012 Express上进行了测试.

Note: All the code presented was tested on VisualStudio 2012 Express.

推荐答案

Raymond Chen在

Raymond Chen describes the dll import mechanism in detail in this series; summing it up, dllimport for functions is essentially a performance optimization.

如果未将函数标记为dllimport,则编译器和链接器会将其视为普通函数,通过静态"函数调用将其解析为在导入库中找到的存根.存根实际上必须从IAT提取导入函数的地址并在其中执行jmp(即,它必须以某种方式将编译器生成的直接调用转换为间接调用),因此在这两个过程中会有一些性能损失.步骤.

If you don't mark a function as dllimport the compiler and the linker will treat it as a normal function, with "static" function calls resolving it to the stub found in the import library. The stub actually has to fetch the address of the imported function from the IAT and perform a jmp there (i.e. it has to somehow convert the direct call that the compiler generated to an indirect call), so there's some performance penalty in this two-step process.

dllimport告诉编译器它必须从编译阶段就通过IAT生成用于间接调用的代码.这样可以减少间接访问,并允许编译器(在函数本地)缓存目标函数地址.

dllimport, instead, tells the compiler that it has to generate code for an indirect call via the IAT right from the compilation phase. This reduces the indirections and allows the compiler to cache (locally to the function) the target function address.

请注意,如MSDN所说,您可以省略仅用于功能;对于数据,它始终是必需的,因为链接器没有一种机制可以对通过间接方式对编译器生成的变量的直接访问进行返工.

Notice that, as MSDN says, you can omit dllimport only for functions; for data it's always necessary, because there's not a mechanism available for the linker to rework the direct accesses to variables generated by the compiler in indirect ones.

(所有这些在经典"链接器时代特别重要;如今,启用链接时代码生成功能,只需让链接器完全生成函数调用/数据访问权限,就可以解决所有这些问题)

(all this was particularly relevant in times of "classical" linkers; nowadays, with link-time code generation enabled, all these points can be worked around by simply letting the linker fully generate the function calls/data accesses)

这篇关于在Visual Studio中dllimport的用例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆