zoukankan      html  css  js  c++  java
  • DLL输入和输出函数—dllinport与dllexport

    Microsoft特殊处

    dllimport和dllexport存储类修饰符是C语言的Microsoft特殊处扩充。这些修饰显式定义了DLL的客户界面(可执行的文件或另外的DLL)。说明为dllexport的函数消除了一个模块定义(.DLL)文件的需要。你可以为数据和对象使用dllimport和dllexport修饰符。

    dllimport和dllexport存储类修饰符必须与扩充的属性语法关键字__declspec一起使用,下面是这样的例子:

    #define DllImport __declspec(dllimport)

    #define DllExport __declspec(dllexport)

    DllExport void func();

    Dllexport int i = 10;

    DllExport int j;

    DllExport int n;

    有关扩充的存储类修饰符的语法的指定信息,参见第3章“说明和类型”中的“扩充的存储类型属性”。

    Microsoft特殊处结束

    定义和说明

    Microsoft特殊处

    DLL界面指的是系统中某个程序中输出的所有已知项(函数和数据);也就是所有说明为dllimport或dllexport的所有项。包括在DLL界面中的所有说明必须指定为dllimport或dllexport属性。但该定义只能指定dllexport属性。例如,如下函数定义生成一个编译器错误:

    #define DLLImport __declspec(dllimport)

    #define DLLExport __declspec(dllexport)

    DLLImport int func()/*错误:在定义中禁止dllimport*/

    {
    return 1;
    }

    下面代码也产生一个错误:

    #define DllImport __declspec(dllimport)

    #define DllExport __declspec(dllexport)

    DllImport int i=10; /*错误:这是一个定义*/

    但如下是正确的语法:

    #define DllImport __declspec(dllimport)

    #define DllExport __declspec(dllexport)

    DllExport int i=10; /*正确:这是一个输出定义*/

    dllexport的使用隐含一个定义,而dllimport隐含一个说明。你必须对dllexport使用extern关键字强制为一个说明;否则,隐含是一个定义。

    #define DllImport __declspec(dllimport)

    #define DllExport __declspec(dllexport)

    extern DllImport int k; /*这是正确的并隐含一个说明*/

    Dllimport int j;

    Microsoft特殊处结束

    用dllexport和dllimport定义联编函数

    Microsoft特殊处

    你可以用dllexport属性定义一个联编函数,在这种情况下,该函数总是被实例化和被输出,无论程序中的任何模块引用该函数。该函数假定是被另一程序输入。

    你也可以用dllimport属性说明一个函数为联编函数,在这种情况下,该函数可以被伸展(从属于/Ob(联编)编译器选项规格)但不能被实例化。在特殊情况中,如果一个联编输入的函数的地址被占用,该函数的地址保留在返回的DLL中。这个行为和占用一个非联编输入的函数的地址相同。在联编函数中的静态局部数据和字符串在DLL和象在单个程序中似的客户(也就是,一个没有DLL界面的可执行文件)之间维护相同的标识符。

    在进行提供输入的联编函数的练习时要小心,例如,如果你修改DLL,不要假设该客户使用该DLL的改变的版本。为了保证你加载适当的DLL版本,重新建立该DLL的客户。

    Microsoft特殊处结束

    dllimport/dllexport的规则和限制

    Microsoft特殊处

    * 如果你说明一个函数没有dllimport或dllexport属性,该函数不认为是DLL界面的部分。因此,该函数的定义必须出现在该模块中或相同程序的另一个模块中。为了使该函数成为DLL界面部分,必须在其它模块中以dllexport说明该函数的定义;否则,在建立客户时产生一个链接器错误。

    * 如果你的程序的单个模块包含相同函数的dllimport和dllexport说明,那么dllexport属性的优先级比dllimport属性的优先级高。但编译器产生一个警告。例如:

    #define DLLimport __declspec(dllimport)

    #define DLLexport __declspec(dllexport)

    DllImport void func1(void); DllExport void func1(void);/*警告:dllexport更优先*/

    * 你不能用一个以dllimport属性说明的数据对象的地址初始化一个静态数据指针。

    例如,如下代码产生一个错误:#define DllImport __declspec(dllimport)#define DllExport __declspec(dllexport) DllImport int i ; . . . int *pi=&i; /* 错误 */ void func2() { static int *pi=&i; /* 错误 */ }

    * 用一个dllimport说明的函数的地址初始化一个静态函数指针,设置该指针为该DLL输入形实替换程序(一个转换控制到该函数的代码块)而不是该函数的地址。如下赋值不产生错误消息:

    #define DllImport __declspec(dllimport)

    #define DllExport __declspec(dllexport)

    DllImport void func1(void)

    . . . static void (*pf)(void)=&func1;/* 没有错误 */

    void func2()

    {

    static void (*pf)(void)=&func1;/* 没有错误 */

    }

    * 因为在一个对象的说明中包括dllexport属性的程序必须提供这个对象的定义,你可以用一个dllexport函数的地址初始化一个全局或局部静态函数指针。类似地,你可以用一个dllexport数据对象的地址初始化一个全局或局部静态数据指针。例如:

    #define DllImport __declspec(dllimport)

    #define DllExport __declspec(dllexport)

    DllImport void func1(void);

    DllImport int i;

    DllExport void func1(void);

    DllExport int i;

    . . .

    int *pi=&i; /* 正确 */

    static void(*pf)(void) = &func1;

    /* 正确 */

    void func2()
    {
    static int *pi=i; /* 正确 */
    static void (*pf)(void) = &func1; /* 正确 */
    }
  • 相关阅读:
    [转]2013豆瓣校园招聘研发类笔试题
    【强烈推荐】《剑指Offer:名企面试官精讲典型编程题》一书中IT名企经典面试题
    [转]2013百度校园招聘-机器学习和数据挖掘工程师-笔试题
    [转]一个应届计算机毕业生的2012求职之路
    图片镜像
    家有学霸的CEO
    盯盯拍Android App 3.0指导
    淘宝领取金币
    儿童散光眼的分类
    女孩被宠坏叫爷爷滚开
  • 原文地址:https://www.cnblogs.com/zhehan54/p/5919959.html
Copyright © 2011-2022 走看看