1 静态库:运行时,不独立存在,会被嵌入(链接)到可执行程序或其他动态库中,目标程序的归档,文件扩展名: LIB
2 动态库:运行时独立存在,不会链接到可执行或其他动态库中,文件扩展名: DLL
3 静态库程序
3.1 特点
1)运行时不独立存在
2)连接到可执行程序或其他动态库中
3)目标程序的归档
3.2 C语言的静态库
3.2.1 静态库的创建
1)建立项目
2)添加库程序,源文件.C文件
3.2.2 静态库的路径设置
1)项目的Setting菜单项中设置
2)可以使用pragma关键字设置
#pragma comment( lib, "../lib/WinClib.lib" )
建立一个C文件,C文件可以在文件中直接使用C库函数,不需要头文件。
3.3 c++语言的静态库
3.3.1 静态库创建
1)建立项目
2)添加库程序,源文件.cpp文件
3.3.2 静态库的使用
1)项目的Setting菜单项中设置
2)可以使用pragma关键字设置
c++语言的静态库需要提供头文件,C语言最好也提供头文件。
注意:CPP环境使用C静态库,库中函数的定义要增加 extern "C"
例如:extern "C" int C_add(int, int);
4 动态库程序
4.1 动态库程序的特点
1)运行时独立存在
2)不会链接到可执行程序或其他动态库中
3)使用时加载
与静态库的比较
1)由于静态库是将源码嵌入到使用程序中,多个程序使用时,会有多份代码,所以代码的体积会增大。动态库的代码只需要一份,其他程序通过函数的地址使用,所以代码的体积小。
2)静态库发生变化,使用(静态库的)程序需要重新编译连接嵌入到使用程序中。
动态库发生变化,如果库中函数定义未发生改变,其他使用DLL的程序不需要重新编译连接。
4.2 动态库的创建
4.2.1 建立项目
4.2.2 添加库程序
4.2.3 库程序导出
提供给使用者库中函数的信息,只有被导出的库程序才能被调用者使用。
4.3 动态库的函数
4.3.1 实现动态库函数
4.3.2 库函数的导出
1)使用_declspec(dllexport) 导出函数,例如:_declspec(dllexport) int Sub(...);
注意:编译连接之后,会有.LIB文件,是作为动态库函数映射使用,与静态库的LIB文件不同,动态库中对应的.lib文件表示函数在动态库中的偏移地址。
2)定义模块文件 .def
LIBRARY DLLFunc //库
EXPORTS //库导出表
DLL_Mul @1 //导出的函数
例如:
LIBRARY WinCdll(库名称)
EXPORTS
CDLL_add @1
CDLL_sub @2
4.4 动态库的使用
4.4.1 隐式连接
1)头文件和函数原型
可以在函数原型的定义前增加_declspec(dllimport),例如:_declspec(dllimport) int Cdll_ADD(.....);
2)导入动态库的LIB文件
1)Setting菜单项中设置
2)使用pragma关键字导入
3)在程序中使用库函数
4)隐式连接的情况,DLL可以存放的路径
1.与可执行程序文件在同一目录下。
2.当前工作目录
3.WINDOWS目录
4.WINDOWS/SYSTEM32目录
5.WINDOWS/SYSTEM目录
6.环境变量PATH指定目录,不建议使用
4.4.2 显示连接, 不会用到.lib文件
1)定义函数指针类型,typedef
2)加载动态库
HMODULE LoadLibrary(
LPCTSTR lpFileName // 动态库的名称(.dll和.exe在一目录下)或全路径
);//返回动态库的实例句柄。
3)获取函数地址
FARPROC GetProcAddress(
HMODULE hModule, // 动态库实例句柄
LPCSTR lpProcName // 函数名称
);//执行成功,返回函数地址。
4)使用函数
5)卸载动态库
BOOL FreeLibrary(
HMODULE hLibModule // 动态库实例句柄
);
注意:
显示连接,获取函数地址时,如果动态库的导出方式为_declspec(dllexport),那么获取函数地址失败。即 显示连接必须使用模块文件(.def)导出的函数,不能使用_declspec(dllexport)导出的函数。
隐式连接,既可以通过在函数原型的定义前增加_declspec(dllimport),也可以使用模块文件(.def)导出函数。
4.4.3 两种链接方式的对比
1)在库函数定义不变的情况下
隐式连接,由于库函数地址时在程序 编译连接,所以当动态库发生变化后,使用程序需要重新编译链接。
显示连接,由于库函数地址是在程序 运行 过程中,动态从库中查询到的,所以库发生变化后不需要重新编译连接。
2)动态库的加载时机不同
隐式链接,动态库是在使用程序启动时就被加载,当动态库不存在,实用程序无法启动。
显示链接,动态库是在调用LoadLibrary函数时才被加载,因此使用程序可以启动,只有程序执行到LoadLibrary函数时,才会出错。
5 DLL中类的使用
5.1 DLL中定义并且实现一个类。
5.2 DLL中类要导出
在类名前增加_declspec(dllexport)
例如:
class _declspec(dllexport) CMath
{
public:
.............
};
通常使用预编译宏开关切换类的导入或导出,例如:
#ifdef DLL_CLASS_EXPROTS
#define EXT_CLASS _declspec(dllexport)
#else
#define EXT_CLASS _declspec(dllimport)
#endif
class EXT_CLASS CMath
{
public:
.............
};
5.3 使用DLL中的类
5.3.1 导入DLL的LIB文件
5.3.2 类的定义 CMath math;
5.3.3 使用类中的成员
6 动态库的程序入口
入口函数不是DLL必须的,常用于DLL内部初始化或善后处理。
动态库的加载和卸载时都会被调用,例如:调用LoadLibrary或 FreeLibrary函数时,会被调用
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // 动态库程序实例句柄
DWORD fdwReason, // 调用原因
LPVOID lpvReserved // 保留
);返回TRUE,表示动态库加载成功。
fdwReason
DLL_PROCESS_ATTACH 进程被加载
DLL_PROCESS_DETACH 进程被卸载
DLL_THREAD_ATTACH 线程被加载
DLL_THREAD_DETACH 线程被卸载
2 动态库:运行时独立存在,不会链接到可执行或其他动态库中,文件扩展名: DLL
3 静态库程序
3.1 特点
1)运行时不独立存在
2)连接到可执行程序或其他动态库中
3)目标程序的归档
3.2 C语言的静态库
3.2.1 静态库的创建
1)建立项目
2)添加库程序,源文件.C文件
3.2.2 静态库的路径设置
1)项目的Setting菜单项中设置
2)可以使用pragma关键字设置
#pragma comment( lib, "../lib/WinClib.lib" )
建立一个C文件,C文件可以在文件中直接使用C库函数,不需要头文件。
3.3 c++语言的静态库
3.3.1 静态库创建
1)建立项目
2)添加库程序,源文件.cpp文件
3.3.2 静态库的使用
1)项目的Setting菜单项中设置
2)可以使用pragma关键字设置
c++语言的静态库需要提供头文件,C语言最好也提供头文件。
注意:CPP环境使用C静态库,库中函数的定义要增加 extern "C"
例如:extern "C" int C_add(int, int);
4 动态库程序
4.1 动态库程序的特点
1)运行时独立存在
2)不会链接到可执行程序或其他动态库中
3)使用时加载
与静态库的比较
1)由于静态库是将源码嵌入到使用程序中,多个程序使用时,会有多份代码,所以代码的体积会增大。动态库的代码只需要一份,其他程序通过函数的地址使用,所以代码的体积小。
2)静态库发生变化,使用(静态库的)程序需要重新编译连接嵌入到使用程序中。
动态库发生变化,如果库中函数定义未发生改变,其他使用DLL的程序不需要重新编译连接。
4.2 动态库的创建
4.2.1 建立项目
4.2.2 添加库程序
4.2.3 库程序导出
提供给使用者库中函数的信息,只有被导出的库程序才能被调用者使用。
4.3 动态库的函数
4.3.1 实现动态库函数
4.3.2 库函数的导出
1)使用_declspec(dllexport) 导出函数,例如:_declspec(dllexport) int Sub(...);
注意:编译连接之后,会有.LIB文件,是作为动态库函数映射使用,与静态库的LIB文件不同,动态库中对应的.lib文件表示函数在动态库中的偏移地址。
2)定义模块文件 .def
LIBRARY DLLFunc //库
EXPORTS //库导出表
DLL_Mul @1 //导出的函数
例如:
LIBRARY WinCdll(库名称)
EXPORTS
CDLL_add @1
CDLL_sub @2
4.4 动态库的使用
4.4.1 隐式连接
1)头文件和函数原型
可以在函数原型的定义前增加_declspec(dllimport),例如:_declspec(dllimport) int Cdll_ADD(.....);
2)导入动态库的LIB文件
1)Setting菜单项中设置
2)使用pragma关键字导入
3)在程序中使用库函数
4)隐式连接的情况,DLL可以存放的路径
1.与可执行程序文件在同一目录下。
2.当前工作目录
3.WINDOWS目录
4.WINDOWS/SYSTEM32目录
5.WINDOWS/SYSTEM目录
6.环境变量PATH指定目录,不建议使用
4.4.2 显示连接, 不会用到.lib文件
1)定义函数指针类型,typedef
2)加载动态库
HMODULE LoadLibrary(
LPCTSTR lpFileName // 动态库的名称(.dll和.exe在一目录下)或全路径
);//返回动态库的实例句柄。
3)获取函数地址
FARPROC GetProcAddress(
HMODULE hModule, // 动态库实例句柄
LPCSTR lpProcName // 函数名称
);//执行成功,返回函数地址。
4)使用函数
5)卸载动态库
BOOL FreeLibrary(
HMODULE hLibModule // 动态库实例句柄
);
注意:
显示连接,获取函数地址时,如果动态库的导出方式为_declspec(dllexport),那么获取函数地址失败。即 显示连接必须使用模块文件(.def)导出的函数,不能使用_declspec(dllexport)导出的函数。
隐式连接,既可以通过在函数原型的定义前增加_declspec(dllimport),也可以使用模块文件(.def)导出函数。
4.4.3 两种链接方式的对比
1)在库函数定义不变的情况下
隐式连接,由于库函数地址时在程序 编译连接,所以当动态库发生变化后,使用程序需要重新编译链接。
显示连接,由于库函数地址是在程序 运行 过程中,动态从库中查询到的,所以库发生变化后不需要重新编译连接。
2)动态库的加载时机不同
隐式链接,动态库是在使用程序启动时就被加载,当动态库不存在,实用程序无法启动。
显示链接,动态库是在调用LoadLibrary函数时才被加载,因此使用程序可以启动,只有程序执行到LoadLibrary函数时,才会出错。
5 DLL中类的使用
5.1 DLL中定义并且实现一个类。
5.2 DLL中类要导出
在类名前增加_declspec(dllexport)
例如:
class _declspec(dllexport) CMath
{
public:
.............
};
通常使用预编译宏开关切换类的导入或导出,例如:
#ifdef DLL_CLASS_EXPROTS
#define EXT_CLASS _declspec(dllexport)
#else
#define EXT_CLASS _declspec(dllimport)
#endif
class EXT_CLASS CMath
{
public:
.............
};
5.3 使用DLL中的类
5.3.1 导入DLL的LIB文件
5.3.2 类的定义 CMath math;
5.3.3 使用类中的成员
6 动态库的程序入口
入口函数不是DLL必须的,常用于DLL内部初始化或善后处理。
动态库的加载和卸载时都会被调用,例如:调用LoadLibrary或 FreeLibrary函数时,会被调用
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // 动态库程序实例句柄
DWORD fdwReason, // 调用原因
LPVOID lpvReserved // 保留
);返回TRUE,表示动态库加载成功。
fdwReason
DLL_PROCESS_ATTACH 进程被加载
DLL_PROCESS_DETACH 进程被卸载
DLL_THREAD_ATTACH 线程被加载
DLL_THREAD_DETACH 线程被卸载