一、Release版本的发布(针对VC++6.0):
如果是VC工具生成的,在release配置中,使用静态库,然后再release编译,最后在release目录下可以找到相应的程序. 菜单栏Build->Set Active configuration, 从中选择Debug版本或者Release版本。设置链接库的位置:菜单栏Project->Settings->General中的Microsoft Foundation Classes的下拉菜单下选择。
二、静态链接库和动态链接库
使用静态库(Use static libary)是把.lib和其他.obj一起build在目标文件中,目标文件可以是.exe,也可以是.dll或.oxc等。一般情况下,可以根本就没有“对应的”.dll文件,如C Run Time(CRT)库。一个例子就是,写一个main(){},build出来并不是只有几个字节,当然有人会说那还有exe文件头呢?是,即使加上文件头的尺寸,build出的执行文件仍然“莫名的大”。实际上那多出来的部分就是CRT静态库。姑且可以把静态库.lib理解成外部程序的obj文件比较合理,它包含了函数的实现。
静态连接库就是把(lib)文件中用到的函数代码直接链接进目标程序,程序运行的时候不再需要其它的库文件;动态链接就是把调用的函数所在文件模块(DLL)和调用函数在文件中的位置等信息链接进目标程序,程序运行的时候再从DLL中寻找相应函数代码,因此需要相应DLL文件的支持。
静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了。但是若使用 DLL,该 DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件。静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。
“每一个lib文件就是若干函数(假设只有函数)的定义”
lib库有两种,一种是包含了函数所在DLL文件和文件中函数位置的信息,称为导出库;一种是包含函数代码本身,一般现有的DLL,用的是前一种库;以前在DOS下的TC/BC等,是后一种库。包含函数原型声明的,是头文件(.h)。
lib有静态lib和动态lib之分。
静态lib将导出声明和实现都放在lib中。编译后所有代码都嵌入到宿主程序
动态lib相当于一个h文件,是对实现部分(.dll文件)的导出部分的声明。编译后只是将导出声明部分编译到宿主程序中,运行时候需要相应的dll文件支持
“通过#include包含这些函数声明的头文件后,我们的应用程序就可以使用lib文件中的函数”
还要指定编译器链接相应的库文件。在IDE环境下,一般是一次指定所有用到的库文件,编译器自己寻找每个模块需要的库;在命令行编译环境下,需要指定每个模块调用的库。
“那他和直接给出那个函数定义的文件,比如.cpp文件,和头文件有什么区别,静态链接库有什么用”
cpp文件是源代码,库文件是编译后的二进制代码,比如你可以调用Windows的API,但是不能看到其源代码一样。
“还有不明白的是,静态链接库中的lib文件只要用到,则整个lib文件的内容都放进了exe文件中,那它是被编译进去还是链接的时候连接进去的呢?”
是在链接的时候将lib链接到目标代码中。
静态链接库(Lib)
在VC++6.0中new一个名称为libTest的static library工程,
并新建lib.h和lib.cpp两个文件,lib.h和lib.cpp的源代码如下:
//文件:lib.h
#ifndef LIB_H
#define LIB_H
extern "C" int add(int x,int y); //声明为C编译、连接方式的外部函数
#endif
//文件:lib.cpp
#include "lib.h"
int add(int x,int y)
{
return x + y;
}
编译这个工程就得到了一个.lib文件,这个文件就是一个函数库,它提供了add的功能。将头文件和.lib文件提交给用户后,用户就可以直接使用其中的add函数了。
标准Turbo C2.0中的C库函数(我们用来的scanf、printf、memcpy、strcpy等)就来自这种静态库。
下面来看看怎么使用这个库,在libTest工程所在的工作区内new一个libCall工程。libCall工程仅包含一个main.cpp文件,它演示了静态链接库的调用方法,其源代码如下:
#include <stdio.h>
#include "..\lib.h"//不可丢失
#pragma comment( lib, "..\\debug\\libTest.lib" ) //指定与静态库一起连接
int main(int argc, char* argv[])
{
printf( "2 + 3 = %d", add( 2, 3 ) );
}
静态链接库的调用就是这么简单,或许我们每天都在用,可是我们没有明白这个概念。代码中#pragma comment( lib , "..\\debug\\libTest.lib" )的意思是指本文件生成的.obj文件应与libTest.lib一起连接
DLL调用有两种方式,一种是静态调用,另外一种是动态调用
(一)静态调用
静态调用是一种显式的调用方式,即在编程的时候便知道了被调用的DLL中的接口函数,在编译链接的时候将DLL与工程生成的exe相关联。以MyApp.dll为例,具体的操作步骤如下:
(1)需要的文件有:MyApp.dll,MyApp.lib,MyApp.h
(2)假设需要调用MyApp.dll的工程为MyTest,首先把MyApp.dll放到MyTest工程目录的Debug或者Release目录下,然后将MyApp.lib和MyApp.h放到MyTest工程目录的根目录下
(3)用VC打开MyTest工程,选中工程,然后选择VC菜单下的Project->Settings
(4)在弹出的对话框中选择Link选项卡,然后在Object/library modules输入框中输入MyApp.lib,点击OK
(5)在工程的FileView下,将MyApp.h文件添加到Header Files目录下
(6)最后在需要调用DLL中的函数的*.cpp文件中包含#include “MyApp.h”
(二)动态调用
动态调用是一种隐式的调用方式,即程序运行过程中装载DLL,然后获取指定函数名称的接口函数,然后再调用之。具体的代码示例如下:
{
HINSTANCE hDllInst = LoadLibrary("MyApp.dll");
if(hDllInst)
{
typedef DWORD (WINAPI *MYFUNC)(DWORD,DWORD);
MYFUNC youFuntionNameAlias = NULL; // youFuntionNameAlias 函数别名
youFuntionNameAlias = (MYFUNC)GetProcAddress(hDllInst,"youFuntionName"); // youFuntionName 在DLL中声明的函数名
if(youFuntionNameAlias)
{
youFuntionNameAlias(param1,param2);
}
FreeLibrary(hDllInst);
}
}