动态链接库的创建和调用方法
来源:互联网 发布:手机电视投影软件 编辑:程序博客网 时间:2024/05/22 12:12
最近在写dll,看了一些网上的资源,自己整理了一下,这里把它贴出来。好了,进入正题。
我今天要讲的主要是非mfcdll,也就是win32 dynamic link library ,如下图所示:
图 1
1. 一个简单的dll示例
如图1所示,在file菜单下new一个个Win32 Dynamic-Link Library工程,取名为simple_dll。在建立的工程中添加如下文件
/* 文件名:simple_dll.h */#ifndef SIMPLE_DLL_H#define SIMPLE_DLL_Hextern "C" int _declspec(dllexport)add(int x, int y);#endif/* 文件名:simple_dll.cpp */#include "simple_dll.h"int add(int x, int y){ return x + y;}如上就建立了一个简单的动态链接库工程。按下F7,或者点击build菜单下的build simple_dll.dll可以在debug文件夹下生成simple_dll.lib和simple_dll.dll文件。
接下来我们编写一个win32 console application工程调用dll中的add函数。在文件菜单下点击新建,new一个win32 console application工程,如下图所示。 名称设为call_simple_dll。
然后把simple_dll工程中的simple_dll.lib和simple_dll.dll拷贝到call_simple_dll工程目下文件夹下。最后在call_simple_dll下新建main.cpp文件。
/**********文件main.cpp**************/#pragma comment(lib,"simple_dll.lib")#include<stdio.h> //.lib 文件中仅仅是关于其对应DLL 文件中函数的重定位信息extern "C" _declspec(dllimport) add(int x,int y);int main(int argc, char* argv[]){ int result = add(2,3); printf("%d",result); return 0;}调用成功,结果显示为5.
2. 调用dll中的函数
dll中的函数有两种调用方式,静态的和动态的。第1节中的例子属于静态调用。动态调用的方式如下:
按照第1节中的方式建立好工程,及main.cpp。具体代码改成如下:
#include <stdio.h>#include <windows.h>typedef int(*lpAddFun)(int, int); //宏定义函数指针类型int main(int argc, char *argv[]){ HINSTANCE hDll; //DLL 句柄 lpAddFun addFun; //函数指针 hDll = LoadLibrary("..\\Debug\\dllTest.dll"); if (hDll != NULL) { addFun = (lpAddFun)GetProcAddress(hDll, "add"); if (addFun != NULL) { int result = addFun(2, 3); printf("%d", result); } FreeLibrary(hDll); } return 0;}编译运行,可以得到和第1节中同样的结果。这里我们可以看到所谓动态调用就是使用了LoadLibrary——GetProcAddress——FreeLibrary三个windows API函数。静态调用和动态调用的区别在于,静态调用需要包含lib描述文件。客户端(即main函数)编译连接的时候,会把dll中该函数的地址绑定到main函数。这样,一旦dll发生改变,那么函数的地址也会发生改变。客户端也必须重新编译连接。而动态调用方式,因为使用后期动态绑定,连接的时候不需要知道函数的具体地址。只有在调用的时候,才进行连接。这样,无论dll中的函数怎么修改,反正在客户端调用时会对该函数的地址进行计算,所以即使dll发生改变,也不需要重新编译客户端程序。这就是动态调用和静态调用最主要的区别。当然大家也可以看到,静态调用代码要简洁一些。所以,如果dll功能固定的话,大家可以采用静态链接的方式。
3. dll中函数的导出
可以看到第1节中我们使用
extern "C" int _declspec(dllexport)add(int x, int y);来声明add函数,这里_declspec(dllexport)的意思就是声明说明(declaration spec)add函数是一个dll导出函数。我们可以把simple_dll.dll用vc6 tools自带的depends工具查看, 如下图,我们可以看到add函数的入口指针为0x00001005 。这样说明将add符号才可以被外界调用。
4.dll中变量的导出
变量的导出方式跟函数基本一样
/*文件名: variable.h */#ifndef _VARIABLE_H_#define _VARIABLE_H_#ifdef EXPORT#define VARIABLE_DLL _declspec(dllexport)#else#define VARIABLE_DLL _declspec(dllimport)#endifextern VARIABLE_DLL int dllglobal;#endif/*文件名:variable.cpp */#define EXPORT#include "variable.h"int dllglobal = 33;在主函数中引用DLL 中定义的全局变量:/* 文件名:main.cpp */#include "variable.h"#include<stdio.h>#pragma comment(lib,"variable.lib")int main(){ printf("%d",dllglobal);}
注意,这里需要将variable.h,variable.lib,variable.dll都拷贝到main.cpp同个文件夹下。否则编译不会成功。
5.dll中类的导出
下面的例子里,我们在DLL 中定义了point 和circle 两个类,并在应用工程中引用了它们。
//文件名:point.h,point 类的声明#ifndef POINT_H#define POINT_H#ifdef EXPORT#define CLASS_DLL _declspec(dllexport)#else#define CLASS_DLL _declspec(dllimport)#endifclass CLASS_DLL point //导入类point{public:float y;float x;point();point(float x_coordinate, float y_coordinate);};#endif//文件名:point.cpp,point 类的实现#define CLASS_DLL#include "point.h"//类point 的缺省构造函数point::point(){ x = 0.0; y = 0.0}//类point 的构造函数point::point(float x_coordinate, float y_coordinate){ x = x_coordinate; y = y_coordinate;}客户端程序#include "circle.h" //包含类声明头文件#pragma comment(lib,"circle.lib");int main(){ circle c; printf("area:%f girth:%f", c.x, c.y); return 0;}
- 创建和调用动态链接库方法
- 动态链接库的创建和调用方法
- 动态链接库的创建和调用方法
- 动态链接库的创建和调用
- 动态链接库的创建和调用
- 动态链接库的创建和调用
- 动态链接库的创建和调用
- 动态链接库的创建和调用
- C/C++中动态链接库的创建和调用
- C/C++中动态链接库的创建和调用
- C/C++中动态链接库的创建和调用
- C/C++中动态链接库的创建和调用
- C/C++中动态链接库的创建和调用
- C/C++中动态链接库的创建和调用
- C/C++中动态链接库的创建和调用
- C/C++中动态链接库的创建和调用
- QT动态链接库(DLL)的创建和调用
- C/C++中动态链接库的创建和调用
- 嵌入式操作系统内核原理和开发(内存分配算法)
- Linux内核移植
- hdoj 1049 Climbing Worm【贪心】
- 流总结
- gmock单元测试框架介绍
- 动态链接库的创建和调用方法
- 【裸单源最短路:Dijkstra算法两种版本】hdu 1874 畅通工程续
- Android中常用的工具类
- WAMP环境配置
- LSH
- C语言中运算符及其优先级
- JavaScript中的Objects
- jQueryMobile的组件之栅格系统(grid)
- 简单的有道词典