zoukankan      html  css  js  c++  java
  • Windows核心编程——动态库的加载与导出

    1.隐示加载与显示加载

    使用动态DLL有两种方法,一种是隐式链接,一种是显式链接,如果用loadlibrary就是显示链接,用lib就属于隐式链接。
    两种方法对于你的程序调用动态库时没有任何区别,只是步骤是不一样的。显式调用麻烦了点,但可以没有相应的lib库;隐式调用,使用起来比较简单,有函数的声明就可以了,但必须有lib库。
    隐式加载默认是加载到内存中的,始终占用内存。
    显示加载,你加载时占用内存,释放了就不占用内存了。如果该DLL已经载入,loadlibrary只是会增加一个引用计数,相同,freelibrary也只是减少引用计数,如果引用计数为0时,DLL才从内存中移除。
    显式和隐式只是对于代码编写时来说的,最后产生的可执行程序,不管是显式和隐式,都是用loadlibrary载入的。显式与隐式不是用在这些方面的,显式加载适合需要动态的选 用DLL的情况。

    2.DLL与exe的依赖关系:

    3.显示加载过程(动态加载)

    调用API的方式来加载dll:

        //宏定义:
        typedef int (*PFN_ADD)(int, int);
        typedef int(*PFN_SUB)(int, int);
        typedef void(*PFN_TEST)();
    

     
      1) LoadLibrary - 将dll加载到进程的内存
        

        //加载dll到进程
        HMODULE hMod = LoadLibrary("dll.dll");
    


      2) GetProcAddress - 获取dll的导出函数的地址,通过函数指针的方式调用
        

        //获取出导出函数的地址
        PFN_ADD pfnAdd = (PFN_ADD)GetProcAddress(hMod, "Add");
        int nVal = pfnAdd(1, 5);
    
        //获取出导出变量的地址
        int* pnTest = (int*)GetProcAddress(hMod, "g_nTest");
        
        //通过序号获取函数地址
        PFN_SUB pfnSub = (PFN_SUB)GetProcAddress(hMod, (LPCTSTR)0x0006);
        nVal = pfnSub(1, 5);
    

     
      3)FreeLibrary - 卸载dll

        //卸载dll
        FreeLibrary(hMod);
    

     

    4.GetProcAddres API是如何区分序号和字符串?

        低64K(0x10000)的地址是不可用的,如果是字符串的地址必高于0x10000,一定在用户区,所以小于0x10000的值是序号,大于的值是字符串地址。

    5.如果一个函数没有导出,能不能调用?

        可以,但我们需要拿到函数的地址
        
         通过计算:模块基址 + 函数与模块基址的偏移 = 函数的地址

        //调用没有导出的函数
        PFN_TEST pfnTest = (PFN_TEST)((int)hMod + 0x11620);
        pfnTest();
    

    6.def导出

    添加 __declspec (dllexport)  测试导出函数,

     depend打开可以看到导出的函数:

     

     导出后是粉碎后的名称。

    如果想知道完整明确的导出函数函数名,可以采用def导出 - 给其他编译器或语言使用
        指定函数导出的名字

    用法:

    添加.def 文件

     

    DEF语法:
        =internalname:内部函数的名称
        @ordinal:序号
        NONAME:此函数不以名字导出,只以序号导出
        PRIVATE:只能显示加载,不能隐式加载
        DATA :导出的是数据。

     注意,使用 .def 文件从 DLL 中导出变量时,不需要在变量上指定 __declspec(dllexport)。但是,在任何使用 DLL 的文件中,仍必须在数据声明上使用 __declspec(dllimport)。

    7.测试def导出:


     

    可以看到函数已被导出:

     

  • 相关阅读:
    一道小学数学题
    Ubuntu下使用git提交代码至GitHub
    C#几个小知识点
    C#中巧用#if DEBUG 进行调试
    使用 HPC Pack 为 Azure 中的 Windows HPC 工作负荷创建和管理群集的选项
    使用 Chef 自动执行 Azure 虚拟机部署
    在 Azure 中管理 Windows 虚拟机的可用性
    什么是 Azure 中的虚拟机规模集?
    从 Azure 下载 Windows VHD
    如何使用 Packer 在 Azure 中创建 Windows 虚拟机映像
  • 原文地址:https://www.cnblogs.com/zhaoyixiang/p/12965868.html
Copyright © 2011-2022 走看看