- CL.exe
1. cl /c [filename] /c为只编译不链接的意思,默认cl.exe工具会在编译之后自动调用LINK.EXE进行链接
2. cl.exe运行需要指定include、lib等环境变量
3. [filename]需要指定文件全名(包含后缀名)
4. C/C++的编译是针对文件进行的 - lib.exe Microsoft库管理工具
用于打包编译后的库文件(obj),使生成一个库文件(lib)
obj文件和lib文件一样,可以直接用于link.exe链接工具中,生成exe可执行文件。lib.exe的作用只是打包,将多个obj打包为一个 - link.exe 链接工具
link [file(s)] /dll选项用来生成一个动态链接库(dll) - 库文件的编写:
库文件中只包含需要的函数及数据即可,不需要main函数,也不能有main函数
库文件的调用者,需要用extern关键字申明要调用的外部函数 - 目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。
静态库是一个或者多个obj文件的打包,所以有人干脆把从obj文件生成lib的过程称为Archive,即合并到一起。比如你链接一个静态库,如果其中有错,它会准确的找到是哪个obj有错,即静态lib只是壳子。
动态库一般会有对应的导入库,方便程序静态载入动态链接库,否则你可能就需要自己LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了。有了导入库,你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。
导入库和静态库的区别很大,他们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。 - 动态链接库(dll)
一般为提高程序可读性,使用#define DllExport __declspec(dllexport)宏定义Dll中需要导出的函数;在每个需要导出的函数前使用DllExport,例如DllExport int multiple(int x,int y)
生成一个Dll的方法:1.使用cl.exe /c [filename]将源文件生成库文件 2.使用link.exe /dll [filename.obj]将此obj文件生成dll
调用Dll的方法一:1. 使用extern指定外部函数名 2.在程序中直接使用将要调用的Dll的函数名 3.链接时加入上一步骤中生成的库文件(.lib) - 方法二:运行时动态加载
C代码示例:
//lib.c
#define DllExport __declspec(dllexport)
DllExport int multiple(int x,int y)
{
return x*y;
}
//libCaller.c
#include "windows.h"
//extern int multiple(int x,int y);
typedef UINT (CALLBACK* LPFNDLLFUNC1)(int,int);
HINSTANCE hf;
LPFNDLLFUNC1 func;
main()
{
hf= LoadLibrary("lib.dll");
if(hf!=0)
{
func = (LPFNDLLFUNC1)GetProcAddress(hf,"multiple");
printf("Multiple:%d\r\n",func(5,12));
FreeLibrary(hf);
}
} - Windows中的.lib文件分两种类型
1.静态库文件,用于编译时供其他对象引用 2.动态链接库的导出文件。链接时使用,无需使用LoadLibrary动态加载。 - Link.exe工具在使用.def文件生成DLL时的两种命令行语句:
1. 如果DEF文件中没有LIBRARY语句,需要同时指定/DEF /DLL选项
2. 如果DEF文件中有LIBRARY语句,只需指定/DEF选项即可生成DLL - Microsoft Visult Studio开发工具中CL.exe工具CL的意思及Compile和Link
- 生成DLL的方式(listed in recommended order of use):
1. 在源文件中使用VC++自定义关键字__declspec(dllexport)
2. 使用包含EXPORTS语句的.def文件
3. 使用Link.exe工具的/EXPORT选项(定义导出函数) - //DEF源文件Sample
EXPORTS
add - //DLL源文件Sample
int add(int x,int y)
{
return x + y;
} - int substract(int x,int y)
{
return x-y;
} - 需要说明的是:使用虚函数,系统要有一定的空间开销。当一个类带有虚函数时,编译系统会为该类构造一个虚函数表(virtual function table),简称(vtable),它是一个指针数组,存放每个虚函数的入口地址。系统在进行动态关联时的时间开销是很少的,因此,多态性是高效的。
-
封装:“封装性”(encapsulation),所谓“封装”,指两方面的含义:一是将有关的数据和操作代码封装在一个对象中,形成一个基本单位,各个对象之间相对独立,互不干扰。二是将对象中某些部分对外隐蔽,即隐蔽其内部细节,只留下少量接口,以便与外界联系,接收外界的消息。这种对外界隐蔽的做法称为信息隐蔽(imformationhiding)。信息隐蔽还有利于数据安全,防止无关的人了解和修改数据。特性:1. 大大降低了操作对象的复杂性