• windows编程:创建DLL


    创建DLL

    Dll是动态链接库的缩写,可以作为附加代码动态映射到进程的地址空间中。

    动态库的一般创建方法如下

     

    方法1、使用 __declspec(dllexport)  方式导出

    一般的框架如下

    //头文件

    #ifndef __MAIN_H__

    #define __MAIN_H__

    #include <windows.h>

     

    #ifdef MAIN_DLL

        #define DLL_EXPORT __declspec(dllexport)

    #else

        #define DLL_EXPORT __declspec(dllimport)

    //在导入dll中的函数的时候,__declspec(dllimport)关键字不是必须的

    //可以直接用extern 修饰 ,但是,如果编译器提前知道某一函数是从dll

    //中导入的话,会产生略微高效的代码,所以建议使用该关键字

    #endif

     

    #ifdef __cplusplus

    extern "C"  //是否使用的是C++,如果使用的是C++ , 则告诉编译器不要改编函 //数名

    {

    #endif

     

    void DLL_EXPORT SomeFunction(const LPCSTR sometext);

     

    //在此处添加需要导出的函数的声明

    //声明的形式如下

    // type  DLL_EXPORT funcName(  arguments  );

     

    #ifdef __cplusplus

    }

    #endif

     

    #endif // __MAIN_H__

     

    // 源文件:

    #include "main.h"

     

    //一个导出函数的创建

    void DLL_EXPORT simpleFunc()

    {

        MessageBoxA(0,  "DLL", "DLL Message", MB_OK | MB_ICONINFORMATION);

    }

     

    extern "C" DLL_EXPORT BOOL APIENTRY DllMain(

    HINSTANCE hinstDLL, //当前载入的dll的模块句柄

     DWORD fdwReason, //DllMain函数被调用的原因(四种)

    LPVOID lpvReserved)//保留参数,现在无用

    {

        switch (fdwReason)

        {

            case DLL_PROCESS_ATTACH://dll在进程中第一次被载入

                break;

            case DLL_PROCESS_DETACH://dll从进程地址空间中被移除

                break;

            case DLL_THREAD_ATTACH://当进程中有新线程创建的时候

                break;

            case DLL_THREAD_DETACH://当进程中某一线程终止的时候

                break;

        }

        return TRUE; //如果成功返回TRUE , 失败返回false

    }

     

    方法2

    使用 DEF 文件 。

    为什么要使用def文件呢???

    有两点:

    1、使用def文件可以实现序号导出

    2、使用ms的编译器的时候,当函数的调用约定为 __stdcall(WINAPI)的时候,

    编译器会对 C函数名进行改编,改编的规则是在函数名前加一个前缀 ,在函数名后加一个 特殊的后缀 , 前缀就是一个下划线 “_” , 而后缀则是 一个 “@”符号加上一个数字 , 该数字表示函数参数的总字节数

    例如

    LPVOID  funcName ( INT iArgument1,INT iArgument2,PVOID pArgument3 );

    函数名为 funcName

    改编后的函数名为 _funcName@12 

    12 = sizeof(INT)*2 + sizeof(PVOID) ;

    而是用def文件的时候,当dll用于其它厂家的编译器的时候,就不会遇到函 数名改编的问题 (例如我现在是用的 code blocks),是用原始函数名就可以

    导出

    使用Def方式导出函数的时候,大致使用的也是上述的代码 ,不过在头文件中

    #define DLL_EXPORT __declspec(dllexport)  这一句代码应该改为

    #define DLL_EXPORT , 即取消 该关键字的使用 。

    作为替代

    现在来新建一个 *.def  文件  文件命名为  xxx.def  名称和工程名一致。

    现在来书写 *.def 文件

    *.def  文件常用的语法也不复杂 , 常用到的关键字就两个 LIBARY  和 EXPORTS

     

    //*.def 文件

    LIBRARY  dLLName

    EXPORTS

    exportFuncName  [@ordinal]/*导出序号*/  [NONAME]/*仅以序号方式导出*/

     

    注:当指定NONAME的时候,dll中不包含函数名的字符串 , 函数仅仅以序号的方式导出 , 当导出函数很多,而且以序号方式导出的时候,有利于减小dll的体积

    此时,调用 GetProcAddress 的方法是 :

    GetProcAddress( handle ,  MAKEINTRESOURCE(ordinal) );

    //利用 MAKEINTRESOURCE 这个宏

    //#define MAKEINTRESOURCE MAKEINTRESOURCEA

    // #define MAKEINTRESOURCEA(i) (LPSTR)((DWORD)((WORD)(i)))

     

    更过def文件的规则此处不列出,可到以下网址查看

    http://msdn.microsoft.com/zh-cn/library/28d6s79h(v=vs.80).aspx

     

    3、还有一种方法:是用 export 开关,同样是用 __declspec(dllexport) 关键字, 但是在头文件

    的开头处加上如下语句:

    #pragma comment(linker, “/export:funcName = _funcName@12”)

    很显然,这种方法非常烦,不建议使用

     

        

  • 相关阅读:
    设计模式_桥梁模式
    C++基础学习教程(一)
    Python图像处理(11):k均值
    Cygwin-安装和配置ssh服务
    LeetCode11:Container With Most Water
    事务四大特征:原子性,一致性,隔离性和持久性(ACID)
    2014微软编程之美初赛第一场第三题 活动中心
    改进xutils下载管理器,使其,在随意地方进行进度更新,以及其它状态监听操作
    IT痴汉的工作现状21-Android开发前景论
    Spring配置文件总结
  • 原文地址:https://www.cnblogs.com/wowk/p/3197763.html
Copyright © 2020-2023  润新知