【win32】day11-windows的库/静态库/动态库
Windows的库
由于项目的复杂程度,或者为了提高代码的
重用率等等,所以才引入了库程序。
库包含两种:
1 静态库:扩展名为LIB的文件,是不能被
加载的程序,可以理解为目标程序的
归档。
2 动态库:扩展名是DLL的文件,是可以被
应用程序加载的程序。
静态库
1 静态库的特点
1.1 目标程序的归档
1.2 静态库的代码会被嵌入到程序当中。
1.3 程序执行时不需要静态库存在
2 C语言静态库
2.1 创建静态库
创建Win32静态库项目,使用*.C文件建立项目。
int C_Add( int nAdd1, int nAdd2 )
{return ( nAdd1 + nAdd2 );
}int C_Sub( int nSub1, int nSub2 )
{return ( nSub1 - nSub2 );
}
2.2 添加静态库函数
2.3 在程序中将静态库导入
2.3.1 项目的Setting里设置, link选项
2.3.2 使用关键字 pragma
#pragma comment(lib, "../lib/winclib.lib")
2.4 使用静态库提供的函数
在C语言程序中,直接使用函数即可。
//导入静态库
#pragma comment(lib, "../lib/winclib.lib")int main( )
{ int nAdd = 0;int nSub = 0;//使用C静态库的函数nAdd = C_Add( 100, 100 );nSub = C_Sub( 100, 100 );printf( "ADD: %d\n", nAdd );printf( "SUB: %d\n", nSub );return 0;
}
3 C++语言的静态库
3.1 创建静态库
创建Win32静态库项目,使用*.CPP文件建立项目。
int CPP_Add( int nAdd1, int nAdd2 )
{return ( nAdd1 + nAdd2 );
}int CPP_Sub( int nSub1, int nSub2 )
{return ( nSub1 - nSub2 );
}
3.2 添加静态库的函数
3.3 导入静态库
3.3.1 项目的Setting里设置
3.3.2 使用关键字 pragma
#pragma comment(lib, "../lib/wincpplib.lib")
3.4 定义库函数的原形
int CPP_Add( int nAdd1, int nAdd2 );
3.5 使用库函数
3.6 注意:
如果在CPP文件使用C语言静态库,定义的
静态库函数原形,需要增加 extern "C".
例如:
extern "C" int C_Add( int nAdd1, int nAdd2 );
// usecpplib.cpp : Defines the entry point for the console application.
//#include "stdafx.h"//导入C++的静态库
#pragma comment( lib, "../lib/wincpplib.lib" )
#pragma comment( lib, "../lib/winclib.lib" )//定义函数原形
int CPP_Add( int nAdd1, int nAdd2 );
int CPP_Sub( int nSub1, int nSub2 );extern "C" {int C_Add( int nAdd1, int nAdd2 );
int C_Sub( int nSub1, int nSub2 );}int main(int argc, char* argv[])
{ //使用C++库函数int nAdd = CPP_Add( 100, 100 );int nSub = CPP_Sub( 100, 100 );printf( "ADD: %d\n", nAdd );printf( "SUB: %d\n", nSub );//使用C库函数int nAdd2 = C_Add( 100, 100 );int nSub2 = C_Sub( 100, 100 );printf( "C_ADD: %d\n", nAdd );printf( "C_SUB: %d\n", nSub );return 0;
}
动态库
1 动态库的好处
1.1 可以提供模块化的方式,方便协调开发。
1.2 对源代码保护
1.3 减小可执行文件的大小
1.4 提供代码的重用率
2 动态库的基本使用方法
2.1 动态库的创建
2.2 加载动态库
2.3 获取并使用库函数、变量或类
2.4 释放动态库
3 动态库的函数
3.1 创建
3.1.1 创建DLL的项目
使用Win32 DLL项目,创建DLL,添加相应的文件。
3.1.2 增加动态库函数
3.1.3 导出动态库函数
3.1.3.1 使用__declspec(dllexport)方式
在函数前增加这个关键字,例如
__declspec(dllexport) int Dll_Add()
3.1.3.2 增加 extern "C" 方式,即
extern "C" __declspec(dllexport)
以C语言方式导出函数
#include "windows.h"
#include "stdio.h"BOOL WINAPI DllMain( HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved )
{printf( "DLL=%p, Reason=", hinstDLL );switch( fdwReason ){case DLL_PROCESS_ATTACH:printf( "DLL_PROCESS_ATTACH\n" );break;case DLL_THREAD_ATTACH:printf( "DLL_THREAD_ATTACH\n" );break;case DLL_THREAD_DETACH:printf( "DLL_THREAD_DETACH\n" );break;case DLL_PROCESS_DETACH:printf( "DLL_PROCESS_DETACH\n" );break;}return TRUE;
}//C++导出方式
__declspec(dllexport) int Dll_Add( int nAdd1, int nAdd2 )
{return ( nAdd1 + nAdd2 );
}
//C的导出方式
extern "C" __declspec(dllexport) int Dll_Sub( int nSub1, int nSub2 )
{return ( nSub1 - nSub2 );
}
//DEF的导出方式
int Dll_Mul( int nMul1, int nMul2 )
{return ( nMul1 * nMul2 );
}
3.1.3.3 使用DEF文件导出
增加扩展名为DEF的文件到项目中.
在DEF文件中添加导出定义.
LIBRARY dllfunc.dll //导出库
EXPORTS //导出表
Dll_Mul @1 //导出函数
Dll_Div @2
LIBRARY dllfunc.dll
EXPORTS Dll_Mul @1
3.2 使用
3.2.1 隐式链接
3.2.1.1 导入LIB
项目的Setting或者使用#pragma导入,例如:
#pragma comment( lib, "../lib/dllfunc.lib")
3.2.1.2 定义函数原形
声明一个和导出函数一致的函数定义.
如果DLL采用extern "C"导出函数,
需要定义extern "C"方式函数原形
3.2.1.3 使用函数
直接函数即可
3.2.1.4 应用程序查找DLL的路径
1) 查找当前应用程序的目录.
2) 当前的工作目录
3) 查找Windows System32的目录
4) 查找Windows System的目录
5) 查找Windows目录
6) 查找环境变量PATH指定路径
// CallDllFunc.cpp : Defines the entry point for the console application.
//#include "stdafx.h"//导入DLL的Lib文件
#pragma comment( lib, "../lib/dllfunc.lib")//定义函数原形
int Dll_Add( int nAdd1, int nAdd2 );
extern "C" int Dll_Sub( int nSub1, int nSub2 );
int Dll_Mul( int nMul1, int nMul2 );int main(int argc, char* argv[])
{ // 使用函数int nAdd = Dll_Add( 100, 100 );int nSub = Dll_Sub( 100, 100 );int nMul = Dll_Mul( 100, 100 );printf("Dll_Add: %d\n", nAdd );printf("Dll_Sub: %d\n", nSub );printf("Dll_Mul: %d\n", nMul );return 0;
}
3.2.2 显示链接
3.2.2.1 加载动态库
HINSTANCE LoadLibrary(
LPCTSTR lpLibFileName );//DLL的路径
返回加载好DLL的句柄
3.2.2.2 定义函数原形对应的函数指针
3.2.2.3 获取函数地址
FARPROC GetProcAddress(
HMODULE hModule,//DLL的句柄
LPCSTR lpProcName );//函数的名称
返回对应函数地址
注意:
1 对于__declspec(dllexport)导出的函数,
由于函数名称发生变化,所以无法使用
函数名称获取对应的函数地址,所以
尽量采用隐式链接的方式.
2 extern "C"或DEF方式导出的函数,
可以正常的使用函数名称获取函数地址.
3.2.2.4 使用函数
3.2.2.5 释放动态库
FreeLibrary
// InvokeDllFunc.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
#include "windows.h"typedef int ( * DLL_ADD )( int nAdd1, int nAdd2 );
typedef int ( * DLL_SUB )( int nSub1, int nSub2 );
typedef int ( * DLL_MUL )( int nMul1, int nMul2 );void UseDll( )
{ //加载动态库HMODULE hDll = (HMODULE)LoadLibrary( "dllfunc.dll" );if( hDll == NULL ){printf( "Load Failed\n");return;}printf( "DLL Handle: %p\n", hDll );//定义函数指针DLL_ADD Dll_Add = NULL;DLL_SUB Dll_Sub = NULL;DLL_MUL Dll_Mul = NULL;//获取函数地址Dll_Add = ( DLL_ADD )GetProcAddress( hDll, "Dll_Add" );if( NULL == Dll_Add ){printf( "Get Dll_Add Failed\n");}printf( "Dll_Add: %p\n", Dll_Add );Dll_Sub = ( DLL_SUB )GetProcAddress( hDll, "Dll_Sub" );if( NULL == Dll_Sub ){printf( "Get Dll_Sub Failed\n");}printf( "Dll_Sub: %p\n", Dll_Sub );Dll_Mul = ( DLL_MUL )GetProcAddress( hDll, "Dll_Mul" );if( NULL == Dll_Mul ){printf( "Get Dll_Mul Failed\n");}printf( "Dll_Mul: %p\n", Dll_Mul );//使用函数int nSub = Dll_Sub( 100, 100 );int nMul = Dll_Mul( 100, 100 );printf( "Dll_Sub: %d\n", nSub );printf( "Dll_Mul: %d\n", nMul );//释放动态库FreeLibrary( hDll );
}int main(int argc, char* argv[])
{UseDll( );return 0;
}
4 动态库的变量
4.1 定义全局变量
4.2 导出全局变量
4.2.1 __declspec(dllexport)导出
__declspec(dllexport) int g_nValue1 = 100;
4.2.2 DEF文件导出
int g_nValue1 = 100;
在DEF文件的导出列表中增加
g_nValue1 @1 DATA
4.3 导入LIB文件
4.4 定义导入变量
需要使用__declspec(dllimport)定义变量.
extern __declspec(dllimport) int g_nValue1;
4.5 使用变量
// usevalue.cpp : Defines the entry point for the console application.
//#include "stdafx.h"//导入LIB
#pragma comment( lib, "../lib/dllvalue.lib")
//定义DLL导入变量
extern __declspec(dllimport) int g_nValue1;
extern __declspec(dllimport) int g_nValue2;int main(int argc, char* argv[])
{printf("g_nValue1 = %d\n", g_nValue1 );printf("g_nValue2 = %d\n", g_nValue2 );return 0;
}
5 动态库的类
5.1 创建动态库并定义类
5.2 从DLL中导出类
在类名称前增加__declspec(dllexport)定义.
class __declspec(dllexport) CMath
{ ... };
5.3 使用时导入LIB文件
5.4 导入类
在类名称前增加__declspec(dllimport)定义.
class __declspec(dllimport) CMath
{ ... };
5.5 使用类
5.6 关于类的导入和导出
1) 定义一个宏,例如:
#ifdef _DLLCLASS_DLL_
#define DLLCLASS_EXT __declspec(dllexport)
#else
#define DLLCLASS_EXT __declspec(dllimport)
#endif //_DLLCLASS_DLL_
2) 根据编译项目,修改_DLLCLASS_DLL_宏声明
对于导出类,需要定义_DLLCLASS_DLL_,
否则不需要定义 _DLLCLASS_DLL_ 宏
3) 类的定义为
class DLLCLASS_EXT CMath
{ ... };
#ifndef _MATH_H_
#define _MATH_H_//定义类导入导出宏
#ifdef _DLLCLASS_DLL_
#define DLLCLASS_EXT __declspec(dllexport)
#else
#define DLLCLASS_EXT __declspec(dllimport)
#endif //_DLLCLASS_DLL_//增加类的导入导出宏
class DLLCLASS_EXT CMath
{
public:int Add( int nAdd1, int nAdd2 );int Sub( int nSub1, int nSub2 );
};
#endif //_MATH_H_
#include "math.h"int CMath::Add( int nAdd1, int nAdd2 )
{return ( nAdd1 + nAdd2 );
}int CMath::Sub( int nSub1, int nSub2 )
{return ( nSub1 - nSub2 );
}
// useclass.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
//导入DLL的LIB文件
#pragma comment( lib, "../lib/dllclass.lib")
//需要类的导入方式的声明
#include "../DllClass/math.h"int main(int argc, char* argv[])
{ //使用DLL中的类CMath math;int nAdd = math.Add( 100, 100 );int nSub = math.Sub( 100, 100 );printf("math.Add = %d\n", nAdd );printf("math.Sub = %d\n", nSub );return 0;
}
6 DllMain 函数
是DLL文件入口函数.当程序加载或者释放
动态库的时候,会自动调用这个函数.
BOOL WINAPI DllMain(
HINSTANCE hinstDLL,//DLL的句柄
DWORD fdwReason,//DLL被调用的原因
LPVOID lpvReserved ); //保留值
fdwReason -
DLL_PROCESS_ATTACH 进程加载
DLL_THREAD_ATTACH 线程加载
DLL_THREAD_DETACH 线程卸载
DLL_THREAD_DETACH 进程卸载
返回值表示是否加载成功.
【win32】day11-windows的库/静态库/动态库相关推荐
- C++中.lib静态库、.dll动态库的生成及调用1
一.前言 1.动态链接库(dll)与静态链接库(lib): 动态链接库(dll)是一个可以被其他应用程序共享的程序模块,其中封装了一些可以被共享的例程和资源.在链接步骤中,连接器将从库文件取得所需的代 ...
- 库文件、静态库(lib)与动态库(dll)的生成与使用
静态库 程序编译一般需经预处理.编译.汇编和链接几个步骤.在应用中,有一些公共代码是需要反复使用,就把这些代码编译为"库"文件:在链接步骤中,连接器将从库文件取得所需的代码,复制到 ...
- C++中.lib静态库、.dll动态库的生成及调用2
关于动.静态库的介绍及静态库的生成及调用参见:C++中.lib静态库..dll动态库的生成及调用<1>,本文主要介绍基于VS2015平台的动态库dll的生成及调用方法. 一.动态库的生成 ...
- Visual studio那些破事。。。(生成静态库、生成动态库、引用静态库、引用动态库)
共4个小步骤,每个小步骤你都可以新建个VS解决方案,自己跟着步骤跑一下,windows怎么[生成静态库.生成动态库.引用静态库.引用动态库]你就基本明白了@! 文章目录 1.导出静态库.lib(add ...
- [转]Linux下g++编译与使用静态库(.a)和动态库(.os) (+修正与解释)
在windows环境下,我们通常在IDE如VS的工程中开发C++项目,对于生成和使用静态库(*.lib)与动态库(*.dll)可能都已经比较熟悉,但是,在linux环境下,则是另一套模式,对应的静态库 ...
- 【Linux后端开发必问】操作系统系列(Linux常用命令、文件权限修改、静态与动态库的制作)
目录 一.说说常用的Linux命令 二.文件权限如何修改 三.静态库和动态库的制作 1.静态库 2.动态库的制作 3.两者优势对比 一.说说常用的Linux命令 1.cd命令:用于切换当前目录: 2. ...
- 【Android NDK 开发】Android Studio 使用 CMake 导入静态库 ( CMake 简介 | 构建脚本路径配置 | 引入静态库 | 指定静态库路径 | 链接动态库 )
文章目录 I . CMake 简介 II . Android Studio 中 CMake 引入静态库流程 III . 指定 CMake 最小版本号 IV . 导入函数库 ( 静态库 / 动态库 ) ...
- 【Android NDK 开发】Ubuntu 函数库交叉编译 ( Android 动态库交叉编译 | Android 静态库交叉编译 )
文章目录 I . Ubuntu 中交叉编译 Android 动态库 II . Ubuntu 中交叉编译 Android 静态库 I . Ubuntu 中交叉编译 Android 动态库 1 . 要编译 ...
- linux库引入之动态库静态库(生成和使用)
库: 库是一种可执行代码的二进制形式,可以被操作系统载入内存执行.就是将源代码转化为二进制格式的源代码,相当于进行了加密,别人可以使用库,但是看不到库中的内容. 如何使用 用户需要同时具有头文件和库. ...
- 在Linux中创建静态库.a和动态库.so
转自:http://www.cnblogs.com/laojie4321/archive/2012/03/28/2421056.html 在Linux中创建静态库.a和动态库.so 我们通常把一些公用 ...
最新文章
- Oracle二三事之 12c 可插拔数据库PDB
- weex的实践踩坑日常(一)
- linux中Shell历史命令记录文件的路径是什么
- FFMPEG结构体分析之AVFrame
- 2017年9月分c语言,2020年9月中国编程语言排行榜
- 《混合云计算》——2.2 结合服务创建混合云环境
- 2010年下半年软件评測师(下午)试题分析与解答
- 02_MySQL约束课堂笔记
- 2021年中国助听器电池市场趋势报告、技术动态创新及2027年市场预测
- 使用递归解决斐波那契数列的性能问题
- java redis jar_Java使用Redis
- 如何自己打印计算机准考证,如何打印计算机准考证
- 联想android电视软件下载,#联想智能电视普及风暴#绕开“乐商店”,大叔教你一步步在智能电视上安装第三方APK...
- C盘扩容好帮手——傲梅分区助手
- 那些年,我们一起喜欢的诺基亚
- mysql数据库基础评分标准_《MYSQL高级查询与编程》综合机试试卷 - 云南农职美和易思...
- 语义分割【论文解读】新思路:几何感知蒸馏 CVPR-2019
- 【代码阅读】PointNet++中ball query的CUDA实现
- 跟着我从零开始入门FPGA(一周入门系列)第二天
- json tobean
热门文章
- 马航37年前一起劫机案被指至今仍是“谜团
- python下标越界怎么解决_切片python字符串时 为何不会引起下标越界?
- 256色图像不一定是灰度图像。
- 云虚拟主机更适合哪些用户使用
- 计算机 校级研究生学术会议,通知 | 【研究生评奖评优】关于做好浙江大学2017-2018学年计算机学院研究生学年小结及评奖评优工作的通知...
- 红外摄像机的原理及选择
- python sql导出excel_python sql导出excel数据库
- Mysql下载详细步骤
- Andriod Studio实现简易音乐播放器
- 知乎|为什么更愿意一个人生活?