静态库在连接阶段,会将汇编生成的目标文件.o与引用到的库一块儿连接打包到可执行文件中。所以对应的连接方式称为静态连接。windows
首先在头文件下添加一个头文件static.h
头文件static.h的内容以下:函数
int sum(int a, int b);//声明函数
在源文件下添加一个源文件static.cpp,内容以下:操作系统
#include "static.h" #include "stdafx.h" int sum(int x, int y){ return x + y;}
在菜单栏选择“生成”->“生成解决方案”就能够了。3d
而后打开工程文件夹,在Debug目录下(编译选择的是默认的Debug和Win32)就能够看到一个和项目名称相同的lib文件:code
这样供给别人调用的lib文件就生成好了,下面讲如何调用这个静态库文件。blog
首先新建另外的项目TestCallLib1,这个项目将使用咱们刚刚生成的静态库
索引
将头文件static.h和静态库TestLib1.lib拷到TestCallLib1\TestCallLib1目录下
接口
首先将主函数写好内存
有两种方法调用静态库:unicode
运行获得结果!
建立动态库关键是导出函数,DLL中导出函数的声明有两种方式:
新建项目win32,应用程序类型选择dll
须要本身手动添加四个文件
头文件dllgenerator.h,内容:
int Add(int, int);int Mul(int, int);
函数定义文件dllgenerator.cpp,内容:
int Add(int a, int b){return a + b;} int Mul(int c, int d){return c * d;}
dllmain.cpp : 定义 DLL 应用程序的入口点
// dllmain.cpp : 定义 DLL 应用程序的入口点。 #include <windows.h> BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
需包含库<windows.h>,里面有不少与生成动态库的相关函数和参数
创建源文件Source.def(划重点)
在此文件第一行引号中填你的项目名称便可,EXPORTS下面列出要生成的函数名称 格式:“名称 @序号”)
LIBRARY "TestDll1" EXPORTS Add @1 Mul @2
点击菜单栏 生成 -> 生成解决方案,咱们的动态库就生成成功了
新建项目过程同上!这里的关键是头文件中须要加入关键字__declspec(dllexport),这个关键字是导出函数的关键!
添加lib.h和lib.cpp函数
生成后一样看见.dll文件和.lib文件
新建项目DLLTestor,将刚刚生成的.dll、.lib、.h文件拷贝到DLLTestor\DLLTestor文件下( .lib、.h 文件不是必须拷入的,我这里并无拷入)
工程调用dll时首先在工程文件目录中查找dll,找不到后在C:\Windows\System32 中找。因此咱们本身项目简单调用dll时就把生成的dll文件复制到工程目录中,若是常常用能够把dll文件放到C:\Windows\System32中
调用动态库是调用 .dll、 .lib、 .h 三个文件
编好代码并设置.lib和.h文件的调用路径
右键“目录”“属性”选择“连接器”->“输入”,在“附加依赖项”这里添加要调用的lib文件的名字:TestDll1.lib
运行获得结果
动态加载是指在生成可执行文件时不将全部程序用到的函数连接到一个文件,由于有许多函数在操做系统带的dll文件中,当程序运行时直接从操做系统中找。
而静态加载就是把全部用到的函数所有连接到exe文件中。动态加载是只创建一个引用的接口,而真正的代码和数据存放在另外的可执行模块中,在运行时再装入;
而静态加载是把全部的代码和数据都复制到本模块中,运行时就再也不须要库了。
#include "stdafx.h" #include "dllgenerator.h" #include "windows.h" int _tmain(int argc, CHAR* argv[]){ printf("Hello World!\n"); HMODULE hmod = LoadLibrary("TestDll1.dll"); // //用于加载dll typedef int(*LoadProc)(int x, int y); LoadProc Load_proc = (LoadProc)GetProcAddress(hmod, "Add"); //GetProcAddress()用于得到函数地址 int iRet = Load_proc(3, 5); //获得地址后调用该函数,返回较大值 printf("the Add the value is:%x\n", iRet); return 0; }
须要理解调用动态库主要用到三个函数,加载LoadLibrary、调用GetProcAddress、释放FreeLibrary!
别忘了在右键“目录”“属性”选择“连接器”->“输入”,在“附加依赖项”这里添加要调用的lib文件的名字:TestDll1.lib
你们在制做过程当中可能会遇到以下的问题
这是字符集的问题,具体的解决方案是:右键项目->属性
把字符集从unicode改为多字节字符集。
目前以lib后缀的库有两种,一种为静态连接库(Static Libary,如下简称“静态库”),另外一种为动态链接库(DLL,如下简称“动态库”)的导入库(Import Libary,如下简称“导入库”)。静态库是一个或者多个obj文件的打包,因此有人干脆把从obj文件生成lib的过程称为Archive,即合并到一块儿。好比你连接一个静态库,若是其中有错,它会准确的找到是哪一个obj有错,即静态lib只是壳子。动态库通常会有对应的导入库,方便程序静态载入动态连接库,不然你可能就须要本身LoadLibary调入DLL文件,而后再手工GetProcAddress得到对应函数了。有了导入库,你只须要连接导入库后按照头文件函数接口的声明调用函数就能够了。导入库和静态库的区别很大,他们实质是不同的东西。静态库自己就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。
通常的动态库程序有lib文件和dll文件。lib文件是必须在编译期就链接到应用程序中的,而dll文件是运行期才会被调用的。若是有dll文件,那么对应的lib文件通常是一些索引信息,具体的实如今dll文件中。若是只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。