VS动态_静态链接库的使用方法

⌚Time: 2022-03-23 23:11:32

👨‍💻Author: Jack Ge

c++的链接库库分为静态、动态链接库两种。使用静态库编译时为静态编译,静态编译将静态库中的代码编译进程序,生成的程序能够独立运行。而使用动态链接库在编译时为动态编译,动态编译不将动态库中的代码编译进程序,生成的程序在运行时需要动态库的支持。

windows下链接库的分类以及加载方式

测试环境vs2005,下面介绍如何使用静态/动态库进行编译


静态库的使用

静态库的使用需要静态库文件.lib和相关的一组头文件

静态库文件:

libaaa.lib

与库相关的头文件:

a.h


#pragma once

int max_number(int,int);

在使用静态库的模块中包含库的头文件,一般包含具有所需功能模块(函数、类等)声明的头文件


#include "a.h"

在需要的地方使用库中的功能


...

max_number(a,b);

...

接下来要为vs指明使用相应的静态库进行编译

方法一:

点击项目,属性

链接器,常规,附加库目录里面,加上所用到的静态链接库所在的目录

同样在链接器,输入,附加依赖项里面加上所用到的库文件的名字

方法二:

在代码中加入下面一句话,告诉链接器使用的库路径就可以了


#pragma comment(lib,"D:\\xxx\\xxx\\libaaa.lib")

之后编译运行即可


动态库的使用

动态库的使用需要动态库文件.dll、伴随动态库的.lib文件以及相关的头文件

动态库文件:

libabc.dll

伴随动态库的生成的.lib文件:

libabc.lib

动态库头文件:

abc.h


#pragma once

#ifdef LIBABC_EXPORTS

#define LIBABC_API __declspec(dllexport)

#else

#define LIBABC_API __declspec(dllimport)

#endif



extern "C" LIBABC_API int multiply(int);

extern "C" class LIBABC_API cABC{

private:

    char symbol;

public:

    cABC(char symbol);

    void print_l();

};

其中的


#ifdef LIBABC_EXPORTS

#define LIBABC_API __declspec(dllexport)

#else

#define LIBABC_API __declspec(dllimport)

#endif

动态库的使用方法有两种,静态加载与动态加载

静态加载

使用vs生成动态库dll文件时,会伴随生成一个lib文件。这个lib文件不是真正的静态链接库,而是动态库的导出文件。在编译时像静态编译一样将其中代码编译进程序,里面不包含真正实现功能的代码,而是包含程序运行时动态库的名字以及函数入口,真正实现功能的还是动态链接库。因此程序运行时还是需要动态链接库的支持。

动态链接库的静态加载方式,编译时需要相关的头文件以及lib文件。

对于动态库的静态加载方式就类似静态库的使用的方法

在需要库功能的模块中包含库的相关头文件


#include "abc.h"

在需要的地方使用库中的功能


...

cABC ca;

ca.print_l();

...

同样的为vs指明编译时用到的lib文件,也是有两种方法,与静态库的编译一模一样

方法一:

链接器,常规,附加库目录里面,加上所用到的lib文件所在的目录

同样在链接器,输入,附加依赖项里面加上所用到的库文件的名字

方法二:

在代码中加入


#pragma comment(lib,"D:\\xxx\\xxx\\libabc.lib")

之后点击编译就可以生成程序了

动态库静态加载方式的特点

动态加载

对于动态加载,在编译时只需要库相关的头文件就可以了。不需要.lib文件

动态加载主要用到三个函数

LoadLibrary()、GetProcessAddress()和FreeLibrary()

对于GetProcessAddress()的使用方法。例如库中存在函数


int multiply(int);

而从库中使用此函数功能,就需要有如下代码,定义一个函数指针类型pFunction(名字自己起),但是返回值与参数要与库中所包含函数的一样


typedef int (*pFunction)(int);

之后用函数指针类型pFunction定义一个函数指针pFun,使用GetProcessAddress()的返回值为其赋值,并且GetProcessAddress()的返回值需要进行pFunction类型转换。


pFunction pFun=(pFunction)GetProcAddress(hDll,"multiply");

之后使用pFun函数即可实现所需要的功能

例子:

main.cpp


#include"abc.h"

#include<windows.h>

#include<iostream>

typedef int (*pFunction)(int);

int main(){

    HINSTANCE hDll;

    hDll=LoadLibrary(L"libabc.dll");

    if(hDll==NULL){

        std::cout<<"load library error!"<<std::endl;

        return -1;

    }

    pFunction pFun=(pFunction)GetProcAddress(hDll,"multiply");

    if(pFun==NULL){

        std::cout<<"get procaddress error!"<<GetLastError()<<std::endl;

        return -2;

    }

    std::cout<<"6的阶乘是:"<<pFun(6)<<std::endl;

    FreeLibrary(hDll);

    system("pause");

    return 0;

}

之后点击编译生成程序即可

动态库动态加载的特点:

使用

由动态编译生成的程序不能直接使用,运行时依赖dll文件。需要将相应的动态链接库文件放入system32或程序所在目录下,windows会在上面的目录搜索所需的dll文件。

如果没有相应的dll文件程序就会出现类似提示


提醒