zoukankan      html  css  js  c++  java
  • 包不包含__declspec(dllimport)的判定

    按照MSDN说明,当链接dll的导出函数时,只需要包含头文件和lib,__declspec(dllimport)修饰符不是必须的,但加上该修饰能使导出函数的调用效率更高。那么,究竟原因是什么?

    不使用 __declspec(dllimport) 也能正确编译代码,但使用 __declspec(dllimport) 使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它可以确定函数是否存在于 DLL 中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨 DLL 边界的函数调用中。但是,必须使用 __declspec(dllimport) 才能导入 DLL 中使用的变量。  

    假设dll导出了一个函数:
      extern "C" __declspec(dllexport) void fun();


    一、如果程序中声明不加__declspec(dllimport),查看调用fun()函数的汇编代码:
         004010AD    call         fun (004010d8)

      其中fun被定义为一个标号(label),如下:
    fun:
         004010D8    jmp          dword ptr [__imp__fun (0040e0e8)]

        上面的符号__imp__fun指向的地址为fun()函数在exe中的导入节。

    二、当声明加上__declspec(dllimport)后,查看调用fun()函数的汇编代码:

         004010AB    call         dword ptr [__imp__fun (0040e0e8)]

        从上面可以看出,加上__declspec(dllimport),编译器链接dll将省略一条jmp语句。

    这是因为:

    1。如果导出函数的声明没有用__declspec(dllimport) 修饰的话,编译器并不知道这个函数是由DLL导出的,所以编译器就把这个函数当作普通的外部引用来对待,产生一个外部引用的符号等着链接器解析。当链接器工作的时候,它是不能修改编译器生成的结果,所以会将该符号解析为对相应函数调入节的间接调用。

    2。如果导出函数的声明用__declspec(dllimport) 修饰的话,编译器一开始就知道这个函数是DLL导出函数,直接编译成对调入节的调用。

  • 相关阅读:
    Flink开发中的问题
    怎么确定一个Flink job的资源
    Flink统计日活
    Flink读取resource资源文件
    Spark-6-如何缓解消除数据倾斜
    Spark-5-如何定位导致数据倾斜的代码
    Spark-4-为何要处理数据倾斜
    集合遍历删除中遇到问题
    1206
    1205
  • 原文地址:https://www.cnblogs.com/k1988/p/3587820.html
Copyright © 2011-2022 走看看