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的库/静态库/动态库相关推荐

  1. C++中.lib静态库、.dll动态库的生成及调用1

    一.前言 1.动态链接库(dll)与静态链接库(lib): 动态链接库(dll)是一个可以被其他应用程序共享的程序模块,其中封装了一些可以被共享的例程和资源.在链接步骤中,连接器将从库文件取得所需的代 ...

  2. 库文件、静态库(lib)与动态库(dll)的生成与使用

    静态库 程序编译一般需经预处理.编译.汇编和链接几个步骤.在应用中,有一些公共代码是需要反复使用,就把这些代码编译为"库"文件:在链接步骤中,连接器将从库文件取得所需的代码,复制到 ...

  3. C++中.lib静态库、.dll动态库的生成及调用2

    关于动.静态库的介绍及静态库的生成及调用参见:C++中.lib静态库..dll动态库的生成及调用<1>,本文主要介绍基于VS2015平台的动态库dll的生成及调用方法. 一.动态库的生成 ...

  4. Visual studio那些破事。。。(生成静态库、生成动态库、引用静态库、引用动态库)

    共4个小步骤,每个小步骤你都可以新建个VS解决方案,自己跟着步骤跑一下,windows怎么[生成静态库.生成动态库.引用静态库.引用动态库]你就基本明白了@! 文章目录 1.导出静态库.lib(add ...

  5. [转]Linux下g++编译与使用静态库(.a)和动态库(.os) (+修正与解释)

    在windows环境下,我们通常在IDE如VS的工程中开发C++项目,对于生成和使用静态库(*.lib)与动态库(*.dll)可能都已经比较熟悉,但是,在linux环境下,则是另一套模式,对应的静态库 ...

  6. 【Linux后端开发必问】操作系统系列(Linux常用命令、文件权限修改、静态与动态库的制作)

    目录 一.说说常用的Linux命令 二.文件权限如何修改 三.静态库和动态库的制作 1.静态库 2.动态库的制作 3.两者优势对比 一.说说常用的Linux命令 1.cd命令:用于切换当前目录: 2. ...

  7. 【Android NDK 开发】Android Studio 使用 CMake 导入静态库 ( CMake 简介 | 构建脚本路径配置 | 引入静态库 | 指定静态库路径 | 链接动态库 )

    文章目录 I . CMake 简介 II . Android Studio 中 CMake 引入静态库流程 III . 指定 CMake 最小版本号 IV . 导入函数库 ( 静态库 / 动态库 ) ...

  8. 【Android NDK 开发】Ubuntu 函数库交叉编译 ( Android 动态库交叉编译 | Android 静态库交叉编译 )

    文章目录 I . Ubuntu 中交叉编译 Android 动态库 II . Ubuntu 中交叉编译 Android 静态库 I . Ubuntu 中交叉编译 Android 动态库 1 . 要编译 ...

  9. linux库引入之动态库静态库(生成和使用)

    库: 库是一种可执行代码的二进制形式,可以被操作系统载入内存执行.就是将源代码转化为二进制格式的源代码,相当于进行了加密,别人可以使用库,但是看不到库中的内容. 如何使用 用户需要同时具有头文件和库. ...

  10. 在Linux中创建静态库.a和动态库.so

    转自:http://www.cnblogs.com/laojie4321/archive/2012/03/28/2421056.html 在Linux中创建静态库.a和动态库.so 我们通常把一些公用 ...

最新文章

  1. Oracle二三事之 12c 可插拔数据库PDB
  2. weex的实践踩坑日常(一)
  3. linux中Shell历史命令记录文件的路径是什么
  4. FFMPEG结构体分析之AVFrame
  5. 2017年9月分c语言,2020年9月中国编程语言排行榜
  6. 《混合云计算》——2.2 结合服务创建混合云环境
  7. 2010年下半年软件评測师(下午)试题分析与解答
  8. 02_MySQL约束课堂笔记
  9. 2021年中国助听器电池市场趋势报告、技术动态创新及2027年市场预测
  10. 使用递归解决斐波那契数列的性能问题
  11. java redis jar_Java使用Redis
  12. 如何自己打印计算机准考证,如何打印计算机准考证
  13. 联想android电视软件下载,#联想智能电视普及风暴#绕开“乐商店”,大叔教你一步步在智能电视上安装第三方APK...
  14. C盘扩容好帮手——傲梅分区助手
  15. 那些年,我们一起喜欢的诺基亚
  16. mysql数据库基础评分标准_《MYSQL高级查询与编程》综合机试试卷 - 云南农职美和易思...
  17. 语义分割【论文解读】新思路:几何感知蒸馏 CVPR-2019
  18. 【代码阅读】PointNet++中ball query的CUDA实现
  19. 跟着我从零开始入门FPGA(一周入门系列)第二天
  20. json tobean

热门文章

  1. 马航37年前一起劫机案被指至今仍是“谜团
  2. python下标越界怎么解决_切片python字符串时 为何不会引起下标越界?
  3. 256色图像不一定是灰度图像。
  4. 云虚拟主机更适合哪些用户使用
  5. 计算机 校级研究生学术会议,通知 | 【研究生评奖评优】关于做好浙江大学2017-2018学年计算机学院研究生学年小结及评奖评优工作的通知...
  6. 红外摄像机的原理及选择
  7. python sql导出excel_python sql导出excel数据库
  8. Mysql下载详细步骤
  9. Andriod Studio实现简易音乐播放器
  10. 知乎|为什么更愿意一个人生活?