温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

静态库和动态库编程技术

发布时间:2020-07-31 18:28:11 来源:网络 阅读:1879 作者:超级极客 栏目:编程语言

(1)库

一、什么是库

    库从本质上来说是一种代码重用的方式,即预先编译可执行代码的二进制格式,

可以被载入内存中,执行,比如C运行库,里面实现了基本的函数,我们无需在写一遍,直接调用接口即可.

库分为静态库和动态库两种,



二、静态库和动态库区别

1.静态函数库

这类库名字一般是xxx.lib,利用静态编译的文件比较大,因为这个函数库的所有数据

都会被整合进目标代码中

优点: 即编译后执行程序不需要外部的函数库支持,因为所有使用的函数都被编译进去了, 

缺点: 如果静态函数库里的东西改变了,那你的程序也必须重新编译.


2.动态函数库

库名字一般是 xxx.dll(也可以包含xx.lib用于编译时的链接处理,也可以不包含,

直接动态调用 ) 

动态函数库不会被编译到目标代码中,你的程序执行到相关代码时才调用库函数.

优点: 因此动态函数库产生的执行文件比较小,因为没有整合到你的程序

动态函数库改变不会影响你的程序。动态函数库升级方便.

缺点: 程序在运行环境中必须提供相应的库,





三、静态库实例

1. 选择Win32项目

静态库和动态库编程技术


2.预编译头,自动生成stdafx.h头文件,作用是获得更快的编译速度

静态库和动态库编程技术


3.添加一个类

静态库和动态库编程技术


4.添加加法接口,和c++一样,不做讲解. 注意函数的实现要放在cpp文件,

虽然没错误, 但是违背了静态库的初衷, 



5.实现单独的接口,不依赖类,比如实现一个减法接口

这样声明 extern "c"让编译器这部分但按c形式进行编译

在头文件

extern "C" 

{

int sub(int a,int b);

int Doubles(int a);

}


6.然后编译生成

静态库和动态库编程技术


7.导入使用,接口声明在.h文件,所以需要.h找到函数,

使用代码导入lib

#pragmacomment(lib,"lib名.lib")

静态库和动态库编程技术


如果你要方便,可以直接放工程目录

静态库和动态库编程技术


如果你的lib文件在别的地方,你可以说设置附加库目录

静态库和动态库编程技术


如果你不想在代码导入lib 可以在这里导入

静态库和动态库编程技术



8.创建对象调用接口

	CTestLib t;
	//调用类接口
	int a = t.Add(10,10);

	//调用函数
	int subs = sub(30,10);
	int dbInter = Doubles(30);







四、动态库实例


1.创建Win32项目,DLL即可


静态库和动态库编程技术



2.DllMain函数

静态库和动态库编程技术

作用: 动态库dll和静态库区别是: 动态库是可以独立运行的文件,

通俗说他和可执行文件没有多大区别

当其他可执行程序(exe或者其他dll)调用该dll时候,系统会执行一个入口函数.

做一些初始化之类的工作,当然这个入口函数和可执行文件exe有一个最大的区别

就是这个入口函数  不是必须的, 也就是说没有这个函数依然能编译dll


参数二表明了系统调用DLL的原因:

DLL_PROCESS_ATTACH  进程加载

DLL_PROCESS_DETACH  进程卸载

DLL_THREAD_ATTACH   线程加载

DLL_THREAD_DETACH   线程卸载

通过这四种情况分析系统何时调用轮到DllMain



3.DLL_PROCESS_ATTACH 

一个程序要调用DLL里的函数,首先要把DLL文件映射到进程的地址空间,

要把一个DLL文件映射到进程的地址空间,两种方法:

静态链接和动态链接的LoadLibrary或者LoadLibarayEx


当一个DLL文件被映射到进程的地址控件时,系统调用该DLL的DllMain函数,

传递fdwReason参数为DLL_PROCESS_ATTACH,这种调用只发生在第一次映射

如果同一个进程来为已经映射进来的DLL再次调用,系统只会增加DLL使用次数,


4.DLL_PROCESS_DETACH  

DLL被从进程地址空间解除,DLL处理该值时,应处理相关清理工作


什么时候DLL被从进程的地址空间解除映射呢?有两种情况

1_) FreeLibrary解除DLL映射(有几个LoadLibrary,就要有几个FreeLibrary)

2_) 进程结束而解除DLL映射,在进程结束前还没有解除DLL时,进程结束会解除

DLL映射,如果是调用 TerminateProcess终止指定进程和其线程

系统就不会调用DLL_PROCESS_DETACH  



5.DLL_THREAD_ATTACH   

当进程创建线程时,系统查看当前映射到进程地址空间中的所有DLL文件映射,

DLL_THREAD_ATTACH会触发


新创建的线程负责执行DLL的DllMain函数, 当所有的DLL都处理完后,系统才运行

进程执行其他的线程函数


每次新建线程都会调用, 线程中建立线程也会调用。



6.DLL_THREAD_DETACH   

线程调用ExitThread结束线程,(线程函数返回时, 系统也会自动调用ExitThread)

系统查看当前进程空间中所有的DLL映射文件, 并DLL_THREAD_DETACH调用DllMain函数

通知所有DLL执行线程清理工作





五、动态库导入导出

1.打开C++ 预处理器

区分动态库是导入的还是导出的

静态库和动态库编程技术


2.有一个自定义的预定义,这个预定义随便是什么,因为这个

只在你这个工程有效,其他的无效



3.如果有这个定义说明是导出

如果没有这个定义说明是导入

现在这个宏定义是定义的,所以他是导出.

静态库和动态库编程技术



4.类名前面添加即可

静态库和动态库编程技术



5.添加类函数

声明 不需要调用形式,  给类添加即可

静态库和动态库编程技术

实现

静态库和动态库编程技术


C语言形式 全局接口 声明前加上调用形式

静态库和动态库编程技术




6.编译生成

静态库和动态库编程技术




7.导入和使用动态库,所以操作和静态库一样,就是多个个DLL文件

这个文件和exe放一个目录,会静态链接



8.动态库还有一种链接方式,动态加载dll: LoadLibrary

所谓动态载入,就是程序运行时候不必一开始就载入dll。

在程序需要的时候,动态加入进来, 

这样我们就不再使用lib来做静态连接, 甚至连,h头文件 都不用了,

直接用GetProcAddress来使用,但是这样的方式来说,都最好只用extern "C"

开头的接口, 



9.下载Depends反编译工具 查看dll的内容

上面3个是类风格的

全局形式的Sub函数

静态库和动态库编程技术



10.通过动态链接使用动态函数链接库

动态调用的函数,你得知道函数原型,才能行.

	HMODULE hdl = ::LoadLibrary(L"TestDll.dll");
	
	if(!hdl)
		printf("load error");

	 //获得接口的函数指针. 第二个参数是函数名
	FUNC_SUB fnuc = (FUNC_SUB)::GetProcAddress(hdl,"Sub");
	if(fnuc != NULL)
	{
		printf("110减去20=%d",fnuc(110,20));
	}
	//解除映射
	::FreeLibrary(hdl);













向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI