• VC++中动态链接库的显示加载和隐式加载的区别


    两种方法对于你的程序调用动态库时没有任何区别,只是你在编程时,步骤是不一样的。显式调用麻烦了点,但可以没有相应的lib库;隐式调用,使用起来比较

    简单,有函数的声明(头文件.h)就可以了,但必须有lib库。

    在VC中两种方式的具体方法:

    一、动态库的隐示调用: 在 VC 工程中直接链接静态输入库XXX.lib,然后即可像调用其它源文件中 的函数一样调用DLL中的函数了。

    二、动态库的显式调用: 显式调用动态库步骤:

      1、创建一个函数指针,其指针数据类型要与调用的 DLL 引出函数相吻 合。

       2、通过 Win32 API 函数LoadLibrary()显式的调用DLL,此函数返回 DLL 的实例句柄。

       3、通过 Win32 API 函数GetProcAddress()获取要调用的DLL 的函数地 址,把结果赋给自定义函数的指针类型。

       4、使用函数指针来调用 DLL 函数。

       5、最后调用完成后,通过 Win32 API 函数FreeLibrary()释放DLL 函数。

    #include <stdio.h>
    #include <Windows.h>
    #include <tchar.h>
    #include<iostream>
    using namespace std;
    int _tmain(int argc, _TCHAR* argv[])
    {
        //HMODULE head;
        HMODULE hModule;
        typedef int (  *fun1)(int ,int );
        typedef int (_cdecl  *fun2)(int ,int );
        hModule=LoadLibrary(_TEXT("../ceshidll.dll"));
        
        fun1 f1 =(fun1)GetProcAddress(hModule,"add");
        if (f1==NULL)
        {   
            cout<<"f1没有导出"<<endl;
            //return -1;
        }
        fun2 f2 =(fun2)GetProcAddress(hModule,"sub");
        if (f2==NULL)
        {   
            cout<<"f2没有导出"<<endl;
            //return -1;
        }
        cout<<f1(1,2)<<endl;
        cout<<f2(2,3)<<endl;
        FreeLibrary(hModule);
        system("pause");
    }
    

    c++调用动态库失败解决办法

    之前写好的程序今天早上过来发现在服务器上出错了,于是就各种查问题,整整一个早上外加下午两个小时都在查这个问题,最终被我找到了问题;

    在程序中我发现LoadLibrary()返回的句柄是空的,于是用GetLastError()看了一下,返回值是193,因此可以断定应该是动态库出问题了,所以就用Depends查看了一下程序中依赖的动态库,发现该动态库还缺少另外的一个动态库,导致程序在加载过程中出现了错误,现在才回想起来,之前因为新需求,在原有的动态库上添加新功能,从而调用了另外的一个库,但是在更新服务器程序的时候忘记把最后依赖的动态库更新到服务器上,因此才出现了这个问题,问题虽小,但是也算是一个教训吧,以后一定会记住的。

    如果程序动态库调用失败,我个人觉得首先就行该查看一下这个库是不是依赖其他的库,在此可以借助Depends查看,如果都不缺,那么就应该查看导出函数的导出方式和主调程序的声明方式是否一致,最后就是确定调用库函数的接口参数是否有问题了。

    要调用动态库必须要包含头文件吗? 

    静态连接必须要。

    动态调用可以不要。不过还是要知道有哪些函数,怎么声明的。

    不一定需要。创建一个库一般处于一下两种目的:
    1、把一些相关的代码,打包成一个库,发布给其它的人用。
    这中情况是最常见的情况,如写 C 语言用到 libgcc。在这种情况下,你除了提供库文件:静态库[ windows 下 .lib,linux .a];动态库:[Windows 下 .dll,Linux 下 .so] 之外,必须提供头文件。头文件是你这个库里面提供了那些接口可以供外界使用。如果没有头文件,其他人无法使用。

    2、为某些软件写插件。
    很多大的项目,都是模块化设计,留有一些特定的接口,方便定制。当程序运行时,会动态加载制定目录下的动态库,运行时调用动态库里面约定好的方法。
    这种情况无需提供头文件,但要按照特定的约定来实现这个库。

    大概就是以上这些情况。

    总结:动态库的两种调用方式

    一、静态调用
    1、添加动态库函数声明头文件
    2、在.h文件中添加如下语句
    #pragma comment(lib, ".\****.lib")
    .\****.lib为动态库的绝对路径。
    就可以调用动态库中的函数了。

    二、动态调用

    1、定义一个与动态库函数接受参数类型和返回值均相同的函数指针类型。
    typedef int (* lpAddFun)(int ,int);
    lpAddFun addFun;
    2、HINSTANCE hDll;
    hDll=LoadLibrary("****.dll");//动态加载DLL模块句柄
    3、得到所加载DLL模块中函数的地址
    addFun=(lpAddFun) GetProcAddress(hDll,"Add_new");
    之后就可以使用

    提示若动态库程序和调用动态库的程序在一个解决方案中可以利用项目依赖项,定义项目生成顺序。也可以在调用动态库程序右键属性 -> c/c++ ->常规的附加包含目录中填入动态库目录。然后用形如
    #ifdef _DEBUG
    #pragma comment(lib,"..\Debug\TestDll.lib")
    #else
    #pragma comment(lib,"..Release\TestDll.lib")
    #endif
    这种方式静态加载动态库

  • 相关阅读:
    教你删除Linux中这些因特殊字符命名无法删除的文件
    xtrabackup进行mysql数据库备份、还原
    Redis示例配置文件
    Docker 的基本概念和操作
    Vue项目目录结构
    Vue前端项目搭建及运行(mac系统)
    编辑vue项目后,运行结果却不变
    如何在 IDEA 中创建并部署 JavaWeb 程序
    听说你对 JavaScript 中的输出挺熟?
    js 常用字符串截取
  • 原文地址:https://www.cnblogs.com/leijiangtao/p/4495814.html
Copyright © 2020-2023  润新知