静态库包括.lib和.h文件,在工程中使用静态库分为3步:
1在工程中加入静态库,有两种方法:
方法一:项目设置中引用.lib,project-setting-link-object/library modules中添加.lib;(需要在tools/options设置正确的引用路径)
方法二:在项目中直接加入lib,project-add to project-files,选择正确的.lib。
2在工程中包括.h文件;(可能 需要在tools/options设置正确的引用路径)
3在工程中使用静态库中的函数.
动态链接库一般包括.lib(导出函数),.h,.dll,使用动态库有两种情况:
1隐式链接,同使用静态库相似,分为三步:引用.lib,包含头文件,使用导出函数;
2动态加载,直接使用LoadLibrary 加载所需的动态库,然后指定所需的导出函数.
一个静态库头文件的例子是
#ifndef _MYMATH_H
#define _MYMATH_H
#ifdef _cplusplus
extern "C"
{
#endif
int Summary(int n);
int Factorial(int n);
#ifdef _cplusplus
}
#endif
#endif
在一些情况下,必须使用动态连接库:
1.多个应用程序共享代码和数据:比如Office软件的各个组成部分有相似的外观和功能,这就是通过共享动态连接库实现的。
2.在钩子程序过滤系统消息时必须使用动态连接库
3.设备驱动程序必须是动态连接库
4.如果要在对话框编辑器中使用自己定义的控件,也必须使用动态连接库
5.动态连接库以一种自然的方式将一个大的应用程序划分为几个小的模块,有利于小组内部成员的分工与合作。而且,各个模块可以独立升级。如果小组中的一个成员开发了一组实用例程,他就可以把这些例程放在一个动态连接库中,让小组的其他成员使用。
6.为了实现应用程序的国际化,往往需要使用动态连接库。使用动态连接库可以将针对某一国家、语言的信息存放在其中。对于不同的版本,使用不同的动态连接库。在使用AppWizard生成应用程序时,我们可以指定资源文件使用的语言,这就是通过提供不同的动态连接库实现的。
MFC支持两类动态连接库的创建: 用户动态连接库; MFC扩展类库。
一个用户动态链接库的例子:
// .cpp
#include<windows.h>
//Declare the DLL functions prototypes
int Summary(int);
int Factorial(int);
//////////////////////////
//DllEntryPoint():The entry point of the DLL
///////////////////////////
BOOL WINAPI DLLEntryPoint(HINSTANCE hDLL,DWORD dwReason, LPVOID Reserved)
{
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
{
//一些初始化代码
break;
}
case DLL_PROCESS_DETACH:
{
//一些用于清理的代码
break;
}
}
return TRUE;
}
//// implementations of the defined functions
// .def
; def file uses semicolon for comments
LIBRARY mymaths
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD SINGLE
EXPORTS
;The names of the DLL functions
Summary
Factorial
使用动态链接库的方法:
1. 生成一个类似于静态链接库头文件的.h文件, 并和动态链接库同时生成的lib文件加到工程中, 使用/编译/链接与使用静态链接库一样. 需要注意的是创建动态链接库时的def文件中LIBRARY后的库名称应该与将要使用的dll文件同名. 这种方法是在程序运行开始就将dll库载入内存, 所以如果程序运行时找不到dll文件将导致程序启动失败.
2. 运行时按需要载入dll. 这种方法不需要动态链接库的.h和.lib文件. 如:
//The instance of the Mymaths.DLL library
HINSTANCE ghMathsDLL=NULL;
//declare the Summary() function from the Mymaths.DLL libray.
typedef int (*SUMMARY)(int);
SUMMARY Summary;
//declare the Factorial() function from
//the Mymaths.DLL library.
typedef int (*FACTORIAL)(int);
FACTORIAL Factorial;
使用前先载入:
//载入Mymaths.DLL文件.
ghMathsDLL=LoadLibrary("DllMath.DLL");
//如果载入DLL失败,提示用户
if(ghMathsDLL==NULL){
AfxMessageBox("Cannot load DLL file!");
return;
}
//获得DLL中Summary函数的地址
Summary=(SUMMARY)GetProcAddress(ghMathsDLL,"Summary");
//获得DLL中Factorial函数的地址
Factorial=(FACTORIAL)GetProcAddress(ghMathsDLL,"Factorial");
或者看下面的例子:
HANDLE hLibrary;
FARPROC lpFunc;
int nFormat;
if(nFormat==JPEG)//如果是JPEG格式,装入JPEG动态连接库
{
hLibrary=LoadLibrary(“JPEG.DLL”);
}
else//是GIF格式
hLibrary= LoadLibrary(“GIF.DLL”);
if(hLibrary>=32)
{
lpFunc=GetProcAddress(hLibrary,”ReadImage”);
if(lpFunc!=(FARPROC)NULL)
(*lpFunc)((LPCTSTR)strFileName);
FreeLibrary(hLibrary);
}
LoadLibrary函数装入所需的动态连接库,并返回库的句柄。如果句柄小于32,则载入库失败,错误含义参见有关手册。GetProcAddress函数使用函数名字取得函数的地址。利用该函数地址,就可以访问动态连接库的函数了。
FreeLibrary通过检查动态连接库的引用计数器,判断是否还有别的程序在使用这个动态连接库。如果没有,就从内存中移去该动态连接库;如果有,将动态连接库的使用计数器减1。LoadLibrary则将引用计数加1。