lib和dll

一. 概念

 静态链接库: 在vc中建立的"Win32 static library"工程,编译生成的结果,后缀名为lib.像常用的c函数strcpy什么的其实就是通过静态库的方式提供的.

 动态链接库: DLL,你知道的..

 

1. 静态链接库

(1) 静态链接库的制作方法

1)写头文件,声明函数,函数前面加上extern "C".

2)写源文件,实现函数.函数前面不必再加extern "C".

3)编译....生成.lib文件.

 

至此,静态库制作完成,把.h文件和.lib文件提供给客户程序.

 

(2) 静态链接库的使用方法

1)包含.h文件.(添加或不添加到工程中都可以,只要路径对了就行)

2)#pragma comment(lib,"****.lib") (当然也可以用setting--link--添加的方法,不过我不喜欢)

 

至此,就可以调用静态库提供的函数了.当客户程序生成exe文件的时候,会把lib全部打包进去,因此,通常生成的文件比较大哦.

 

(3) 题外话

1)实际上,.h文件也可以客户程序自己写,只要函数声明与静态库的一致,且,最重要的,函数声明前必须加上extern "C"

2)可以用extern "C" {}的方式,在{}中写多个函数声明,这样就不必每个函数都加上extern "C"了.

3)普通函数,仅有声明,没有实现,是会出现编译错误的.

 

2.动态链接库

首先写点调试动态库的技巧:

那就是将库工程和应用工程(调用库的工程)放置在同一VC工作区,只对应用工程进行调试,在应用工程调用库中函数的语句处设置断点,执行后按下F11,这样就单步进入了库中的函数。另外,动态库默认生成的.lib文件是放在本工程目录中的,如果要指定输出到别的目录,可以在setting--link中增加/implib:"../Debug/**.lib".

 

首先从传统win32动态库说起.
(1)动态库的制作
1)写头文件,声明函数,导出函数前加修饰 extern "C" _declspec(dllexport),如果不采用.def的话,这个修饰符必须加,否则就不是导出函数。
2)写源文件,实现函数.
3)编译..生成.dll和.lib文件

题外话:
1)动态库的.lib文件和静态库的.lib文件是不一样的,它仅包含导出函数/导出变量的声明,实现部分在dll文件中.关于动态库的.lib文件和.dll文件的关系,可以这么描述:当程序员通过静态链接方式编译生成应用程序时,应用程序中调用的与.lib文件中导出符号相匹配的函数符号将进入到生成的EXE文件中,.lib文件中所包含的与之对应的DLL文件的文件名也被编译器存储在EXE文件内部。当应用程序运行过程中需要加载DLL文件时,Windows将根据这些信息发现并加载DLL,然后通过符号名实现对DLL函数的动态链接。这样,EXE将能直接通过函数名调用DLL的输出函数,就象调用程序内部的其他函数一样。
2)__cdecl和__stdcall属于函数调用规范._declspec(dllexport)和_declspec(dllimport)属于导出函数声明.它们不是一个概念.
3)在上述描述中,没有提到动态库的入口函数DllMain,因为DllMain函数可以不写,此时windows会提供一个默认的什么也不操作的DllMain, 不过为了编写规范,通常应该加上DllMain.其原型为BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved).其中APIENTRY即为__stdcall,定义在<windows.h>中.
4)前面提到导出函数使用 extern "C" _declspec(dllexport)来指定。还有另外一种指定导出函数的方法,就是使用.def文件,如果使用.def 文件声明了导出函数则不必使用extern "C" _declspec(dllexport)。.def文件通常添加text文件命名为*.def即可。.def文件是动态库自己用来指定导出函数的,不提供给客户程序使用。下面引用网上一段话描述下.def文件里面各项的概念:

 

  .def文件的规则为:

  (1)LIBRARY语句说明.def文件相应的DLL,即DLL文件的名字;

  (2)EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调用时,这个序号将发挥其作用);

  (3).def 文件中的注释由每个注释行开始处的分号 (;) 指定,且注释不能与语句共享一行。

 

示例如下:

 

; DictComp.def : Declares the module parameters for the DLL. // ;开头的都是注释

 

LIBRARY      "DictComp" // 动态库的名字

DESCRIPTION  'Dictionary Component Windows Dynamic Link Library'

 

EXPORTS

    ; Explicit exports can go here

CreateObject @1 // 导出的函数,如果导出多个,则依次为@2 @3....

 

5) dll的导出函数可以不使用__stdcall约定,但好的习惯是使用__stdcall约定。__stdcall与_declspec(dllexport)的顺序如下:extern "C" void _declspec(dllexport) __stdcall ShowDialog();否则顺序颠倒会报警
如果函数的声明中使用了__stdcall,则其定义中也要带上__stdcall。如果动态库的导出函数指定了__stdcall,则在客户程序中定义函数指针时,也要指定为__stdcall,否则,报vc++错误。

使用示例:动态库中int __stdcall add(int x, int y);客户程序中typedef int(__stdcall *lpAddFun)(int, int);。另外关于__stdcall引用网上一段描述:

如果通过VC++编写的DLL欲被其他语言编写的程序调用,应将函数的调用方式声明为__stdcall方式,WINAPI都采用这种方式,而C/C++缺省的调用方式却为__cdecl。__stdcall方式与__cdecl对函数名最终生成符号的方式不同。若采用C编译方式(在C++中需将函数声明为extern "C"),__stdcall调用约定在输出函数名前面加下划线,后面加“@”符号和参数的字节数,形如_functionname@number;而__cdecl调用约定仅在输出函数名前面加下划线,形如_functionname。


(2)动态库的调用
1)静态调用(又名 静态加载,静态链接,隐式链接)

①不使用动态库提供的.h文件,由客户程序自己对用到的导入函数进行声明。
类似于静态链接库的使用,只不过.h文件换成了.dll文件.也就是说静态调用需要.dll和.lib两个文件.
a.#pragma comment(lib,"")包含.lib文件
b.声明需要的来自于dll的函数,导入函数前加修饰 extern "C" _declspec(dllimport)

c.把.dll文件放入目录
d.使用函数.

②使用动态库提供的.h文件,客户程序使用此.h文件对导入函数进行声明。

即,需要三个文件.h、.lib、.dll

a.#include"*.h"包含头文件

b.#pragma comment(lib,"")包含.lib文件

c.把.dll文件放入目录
d.使用函数.

2)动态调用(又名 动态加载,动态链接,显示链接)

动态调用不需要动态库的.lib文件。

a.定义来自于dll的函数指针,定义函数指针不需要加_declspec(dllimport).

如:typedef int (*lpAddFunc) (int x, int y);

b.使用LoadLibrary()链接动态库
c.定义函数指针对象
如:lpAddFunc pAdd = (lpAddFunc)GetProcAddress(hDll, "add");
d.调用函数指针
如:pAdd(1,2);
e.使用FreeLibrary()释放动态库
关于动态库有篇好文章: http://soft.yesky.com/lesson/318/2166818.shtml  深入浅出Visual C++动态链接库(Dll)编程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值