DLL 与 静态链接库
DLL是跨语言的,各种语言编写的DLL都可以相互调用。
静态链接库
编译的链接阶段将库函数嵌入到应用程序的内部。
动态链接库
对公用的库函数,系统只有一个拷贝(一般是位于系统目录的*.DLL文件),而且只有在应用程序真正调用时,才加载到内存。在内存中的库函数,也只有一个拷贝,可供所有运行的程序调用。当再也没有程序需要调用它时,系统会自动将其卸载,并释放其所占用的内存空间。
DLL的缺点是应用程序不能独立运行,需要在操作系统中另外安装对应的DLL。例如,如果你的MFC项目被设置成“在共享DLL中使用MFC”的,则虽然生成的可执行程序很小,但是在其他没有安装Visual C++(运行环境)的机器上是不能直接运行的,需要另外安装MFC的动态链接库(如mfc90.dll)。
DLL 查找顺序
- 所在目录——当前进程的可执行模块所在的目录,即应用程序的可执行文件(*.exe)所在的目录。
- 当前目录——进程的当前目录。
- 系统目录——如C:\Windows\ System32。可用GetSystemDirectory函数检索此目录的路径。
Windows目录——Windows操作系统安装目录,如C:\Windows\。可用GetWindowsDirectory函数检索此目录的路径。 - 搜索目录——PATH环境变量中所包含的自动搜索路径目录,一般包含C:\Windows\和C:\Windows\System32\等目录。可在命令行用Path命令来查看和设置,也可以通过(在“我的电脑”右键菜单中选“属性”菜单项)“系统属性”中的环境变量,来查看或编辑“Path”系统变量和“PATH”用户变量。
MFC DLL 的类型
使用MFC编写的DLL,可以分成几类:
- 规则DLL——(regular) DLL 中所包含的函数,可以被所有windows应用程序使用
- 共享MFC——DLL中不包含MFC库函数,需要另外安装MFC动态链接库后才能使用
- 静态MFC——DLL中包含MFC库函数,可以脱离MFC动态链接库独立使用
- 扩展DLL——扩展(extension) DLL 中所定义的类和函数,只能被所在MFC 应用程序使用,而且扩展DLL中不能包含MFC库函数,也需要另外安装MFC动态链接库后才能使用。
导出函数的方法
使用MFC创建DLL时,从项目中导出函数到DLL文件的方法有:
- 使用模块定义文件.def
- 使用__declspec(dllexport) 关键字或其替代宏AFX_EXT_CLASS
对每个函数只需要用一种方法即可。
DEF文件只能用来导出函数,不能用于导出整个类。导出C++类,必须用__declspec(dllexport)关键字或其替代宏 AFX_EXT_CLASS。
生成静态链接库示例
新建一个libTest win32 static dll 项目。
新建 CMyMath 类
MyMath.h
#pragma once
class CMyMath
{
public:
CMyMath(void);
~CMyMath(void);
int Add(int a,int b);
int m_a;
};
extern int g_sum;
extern int Mult(int a,int b);
MyMath.cpp
#include "stdafx.h"
#include "MyMath.h"
int g_sum = 0;
int Mult(int a,int b){
return a*b;
}
CMyMath::CMyMath(void):m_a(0)
{
}
CMyMath::~CMyMath(void)
{
}
int CMyMath::Add(int a,int b){
return a+b;
}
编译生成libTest.lib
使用这个静态链接库
新建一个win32 console程序。
配置头文件和库文件。
使用代码:
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "MyMath.h"
int _tmain(int argc, _TCHAR* argv[])
{
CMyMath myMath;
int a = myMath.Add(3, 4);
int b = Mult(3, 4);
int c = g_sum;
int d = myMath.m_a;
printf("%d %d %d %d \n", a, b, c, d);
getchar();
return 0;
}
运行结果:
VS2012 C++项目里面添加静态库文件lib 步骤
方法1: 通过设置工程配置来添加lib库.
A、添加工程的头文件目录:工程—属性—配置属性—c/c++—常规—附加包含目录:加上头文件存放目录。
B、添加文件引用的lib静态库路径:工程—属性—配置属性—链接器—常规—附加库目录:加上lib文件存放目录。
C 然后添加工程引用的lib文件名:工程—属性—配置属性—链接器—输入—附加依赖项:加上lib文件名。
这种方法比较繁琐,且不直观,而且还可能要争对debug版本和release版本作不同的配置,因为我们生成的两个版本的库可能放在不同的目录中的.
方法2: 使用编译语句:
#ifdef _DEBUG
#pragma comment(lib,"..\\debug\\LedCtrlBoard.lib")
#else
#pragma comment(lib,"..\\release\\LedCtrlBoard.lib")
#endif
这种方法直观,方便,且可以按如上直接区分出Debug版本和Release版本的不同目录.当然,通过宏,还可以区分更多版本.
但是在指定目录时,不小心容易出错.
方法3: 直接添加库文件到工程中.
就像添加.h和.cpp文件一样,把lib文件添加到工程文件列表中去.
VC中,切换到”解决方案视图”,—>选中要添加lib的工程–>点击右键–>”添加”–>”现有项”–>选择lib文件–>确定.
就是这么简单,搞定.
这个方法适用于在工程的debug版本和Release版本中都使用同一个lib库文件时.这样就省去了你1方法配置环境的繁琐,也省去了方法2种语句的可能性错误发生.