静态库和动态库的生成和调用

本文深入解析静态库与动态库的区别,涵盖编译过程、生成及调用方法。通过实例展示VS2010环境下动态库的创建与使用,以及如何在程序中隐式或显式链接库文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本概念
程序编译一般需经预处理、编译、 汇编和链接几个步骤。在我们的应用中,有一些公共代码是需要反复使用,就把这些代码编译为“库”文件。

静态库:在链接步骤中,连接器将从库文件取得所需的代码,复制到生成的 可执行文件中。这种库称为静态库,其特点是 可执行文件中包含了库代码的一份完整拷贝;缺点就是被多次使用就会有多份冗余拷贝。

动态库:DLL 是一个包含可由多个程序同时使用的代码和数据的库。Windows下动态库为.dll后缀,在linux在为.so后缀。

在VS中新建生成静态库的工程,编译生成成功后,只产生一个.lib文件;新建生成动态库的工程,编译成功后,产生一个.lib文件和一个.dll文件。既然都产生lib文件,那它们有什么区别呢?
静态库中的lib:包含函数代码本身(即包括函数的索引,也包括实现),在编译时直接将代码加入程序当中。
动态库中的lib:包含了函数所在的DLL文件和文件中函数位置的信息(索引),函数实现代码由运行时加载在进程空间中的DLL提供。
总之,lib是编译时用到的,dll是运行时用到的。如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll。

如何生成动态库
本人使用的是VS2010,步骤如下:
① 新建项目–win32项目–填写项目名–确定–下一步–应用程序类型:选择DLL–附加选项:选择导出符号–完成
②可以看到生成了一个dllmain.cpp 文件,这是dll应用程序的入口,注意它和普通工程的入口main函数不同,这个文件我们不需要修改。

在这个动态库中我们举例导出一个变量(int nMyDLL),一个类(CMyDLL),一个函数(int fnMyDLL(void))。
在这里插入图片描述
新建生成dll的工程时,vs默认定义了宏MYDLL_EXPORT(在预处理器定义中可以看到,下图所示), 因此,MYDLL_EXPORT是 __declspec(dllexport),用来导出。当我们在静态调用dll时,我们包含该头文件,此时由于没有定义MYDLL_EXPORT,所以MYDLL_EXPORT是__declspec(dllimport),用来导入。可以发现,使用这种方式进行宏定义,一举两得,代码复用同时又降低了维护成本。如果我们想同时实现_32位和_64位程序、Debug版本和Release版本 都可以采用这种方式。
在这里插入图片描述
③在定义类时,在类名前加上这个宏,来表明该类是导出类还是导入类。最后一行导出函数还可以写成:

extern "C" MYDLL_API int fnMyDLL(void);

extern “C” 是为了保证编译时生成的函数名不变,这样动态调用dll时才能正确获取函数的地址。

下图是MyDLL.cpp
在这里插入图片描述
如何调用动态库
调用动态库有两种方法:隐式链接显示链接

调用动态库:隐式链接
隐式链接 需要.h文件,dll文件,lib文件

(1)将dll放到工程的工作目录

(2)设置项目属性–vc++目录–库目录为lib所在的路径

(3)将lib添加到项目属性–链接器–输入–附加依赖项(或者直接在源代码中加入#pragma comment(lib, “**.lib”))

(4)在源文件中添加.h头文件

然后就像平常一样调用普通函数、类、变量

调用动态库:显示链接
显示链接 只需要.dll文件,但是这种调用方式不能调用dll中的变量或者类(你想想,连头文件都没有,怎么调用?)。
显示调用主要使用WIN32 API函数LoadLibrary、GetProcAddress,例如:

typedef int (*dllfun)(void);//定义指向dll中函数的函数指针类型

HINSTANCE hlib = LoadLibrary(".\\MyDLL.dll");
if(!hlib)
{
	std::cout<<"load dll error\n";
	return -1;
}

dllfun fun = (dllfun)GetProcAddress(hlib,"fnMyDLL");//定义函数指针fun
if(!fun)
{
	std::cout<<"load fun error\n";
    return -1;
}

fun();

生成静态库
相比动态库,静态库的生成和调用就简单多了。
①新建项目–win32项目–填写项目名–确定–下一步–应用程序类型:选择静态库。
②静态库项目没有main函数,也没有像dll项目中的dllmain。
创建项目后添加.h文件,添加相应的导出函数、变量或类,如下所示

#ifndef _MYLIB_H_
#define _MYLIB_H_

void fun(int a);

extern int k;

class testclass
{
public:
    testclass();
    void print();
};

#endif

cpp文件

#include "stdafx.h"
#include "lib.h"
#include <iostream>

void fun(int a)
{
    std::cout<<a<<"lib gen\n";
}

int k = 42;

testclass::testclass()
{
    std::cout<<"123\n";
}

void testclass::print()
{
    std::cout<<"this is testcalss\n";
}

使用静态库
需要.h文件,lib文件

(1)设置项目属性–vc++目录–库目录为lib所在的路径

(2)将lib添加到项目属性–链接器–输入–附加依赖项(或者直接在源代码中加入#pragma comment(lib, “**.lib”))

(3)在源文件中添加.h头文件

然后就像平常一样调用普通函数、类、变量,举例如下:

#include <iostream>
#include "lib.h"

#pragma comment(lib, "lib.lib")

int main()
{
    fun(4);
    std::cout<<k<<std::endl;
    testclass tc; 
    tc.print();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值