C++:………….lib.dll


#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "user32.lib")			//<-----------------------------------这

void main()
{
return 0;
}


系统提供了一些API,他们简化了开发人员的工作提高了其效率,怎么使用他们呢,因为其实现都放到了dll中,我们要包含头文件,连接他们的库,也就是你提到的这些,这样我们才能使用。(http://zhidao.baidu.com/question/55216828.html)
 

我的项目设置里已经包含了user32.lib,所以
#pragma comment(lib, "user32.lib")
可以删掉。


这些lib在这个文件夹里:




------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

from:http://blog.163.com/laorenyuhai126@126/blog/static/1935077920103182310625/


.h用于编译阶段的审核,如在math.h中有函数声明:
int abs(int);
但是在使用中写为
#include <math.h>
...abs(3,5);
编译器阶段就会检测出错误。



.lib用于链接阶段,在链接各部分目标文件(通常为.obj)到可执行文件(通常为.exe)过程中,需要在.lib文件中查找动态调用函数(一般为DLL中的函数)的地址信息,此时需要在lib文件中查找,如查找SetWindowText()函数的地址偏移就需要查找user32.lib文件。(.lib也可用于静态链接的内嵌代码)

  .lib是在你的程序编译连接的时候就连接的文件,因此你必须告知编译器连接的lib文件在那里。一般来说,与动态连接文件相对比,lib文件也被称为是静态连接库。



.dll用于运行阶段,如调用SetWindowText()函数等,需要在user32.dll中找到该函数。DLL可以简单认为是一种包含供别人调用的函数和资源的可执行文件。

  .dll是在你的程序运行的时候才连接的文件,因此它是一种比较小的可执行文件格式,.dll还有其他的文件格式如.ocx等,所有的.dll文件都是可执行。  

Windows API中的所有函数都包含在DLL中。其中有3个最重要的DLL,Kernel32.dll,它包含用于管理内存、进程和线程的各个函数;User32.dll,它包含用于执行用户界面任务(如窗口的创建和消息的传送)的各个函数;GDI32.dll,它包含用于画图和显示文本的各个函数。


----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

实践一下:

1、创建一个动态链接库项目:


2、编辑:

_declspec(dllexport):是一个声明,将一个函数声名为导出函数,就是说这个函数要被其他程序调用,即作为DLL的一个对外函数接口。


3、编译+链接后得到我们要的.dll,.lib:


4、我们可以通过VS自带的dumpbin工具(我的在C:\Program Files\Microsoft Visual Studio\VC98\Bin目录下,如果你的dumpbin不能用,请先运行“C:\Program Files\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT”)查看一下我们的dll文件的某些信息:进入dll1.dll文件所在目录;

(注:我们通过VS自带的dumpbin工具来查看一个DLL或EXE中的包含的函数或是依赖的函数之类的信息,具体应用信息可以百度、谷歌“DUMPBIN 实用程序的说明”,我们只需要知道它大体用来做什么就好了,需要时在查看参考资料就好了)

至此,我们创建了自己的DLL、LIB,那么,我们怎样使用他们呢:
-- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5、
要使用我们的动态链接库:往往需要两个文件:DLL文件、LIB引入库文件;就是上面我们生成的两个文件。

在我们的dll1.dll、dll1.lib中:

dll1.dll文件包含实际的函数和数据;

dll1.lib文件包含被DLL文件导出的函数和变量的符号名。

在编译时一定要有dll1.lib文件;在运行时一定要有dll1.dll文件。

6、

创建一个项目来检测一下我们的链接库:


#include <iostream>
using std::cout;
using std::endl;

#pragma comment(lib, "dll1.lib")

//
//extern add(int a,int b);

//_declspec(dllimport):告诉编译器,函数来自一个动态链接库,编译器会比extern声明生成执行效率更高的代码;
_declspec(dllimport) int add(int a,int b);

int main(){
	cout<<"1+1="<<add(1,1)<<endl;
	return 0;
}
注意文件夹结构(要将我们的DLL、LIB拷贝到这个测试项目中来,如果不拷贝,由上文的理论,会出现相应的链接、运行错误):


运行,得到期待的结果:


-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
7、
通过DUMPBIN来查看一下可执行文件dll1Test.exe用到了哪些DLL以及其中的函数:



还可以通过VS自带的dependency walker来看可执行程序、DLL、函数之间的依赖关系:



8、关于加载动态链接库的说明:

我们上面将dll1.dll文件放到了当前目录,即,我们创建的项目的那个文件夹。

将上面的DLL文件从当前目录中去掉,会看到,系统为了查找这个dll文件,都查找了哪些目录(我的就显示了一个简略信息,大家可以看看自己的。)

debug----》当前目录----》系统路径……


-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

9、

为了使其他人能够更方便的使用我们提供的动态链接库,而不是通过各种工具来揣测我们的dll文件用来干嘛。

我们需要相应地提供一个源文件(包含一些注释)给用户:



调用的项目:



10、整个程序源码:

dll1项目:

//D:\Workspace\C++\dll1\dll1.h
#ifndef DLL1_API
#define DLL1_API _declspec(dllimport)
#endif
DLL1_API int add(int a,int b);

//--------------------------------------------------------------------------------------

//D:\Workspace\C++\dll1\dll1.cpp

#define DLL1_API _declspec(dllexport)
#include "dll1.h"

DLL1_API  int add(int a,int b){
return a+b;}


编译链接后将DLL、LIB拷到dll1Test项目下;

dll1Test项目:

//D:\Workspace\C++\dll1Test\dll1Test.cpp
#include <iostream>
#include "../dll1/dll1.h"
using std::cout;
using std::endl;
#pragma comment(lib, "dll1.lib")


int main(){
	cout<<"1+1="<<add(1,1)<<endl;
	return 0;
}

OK,完成!


11、其他:


从上面看出,DLL里面的函数名是经过函数名改编,当将某种编译器编译得到的DLL\LIB用于另一种编译器编译的项目时,由于他们对名称改编的方案不同,会不能正确找到函数,导致调用失败

解决C与C++相互调用问题的方法:

export时不要改编函数名,imports时也不要改编函数名:

extern "C"只能确保全局函数不发生函数名改编

#define DLL1_API extern "C" _declspec(dllexport)
#define DLL1_API extern "C" _declspec(dllimport)

………………


(上面的例子来自孙鑫的VC教程!)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值