码迷,mamicode.com
首页 > 其他好文 > 详细

调用DLL的步骤

时间:2015-08-31 21:48:52      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:c语言   dll   

       比较大的应用程序都由很多模块组成,这些模块分别完成相对独立的功能,它们彼此协作来完成整个软件系统的工作。其中可能存在一些模块的功能较为通用,在构造其它软件系统时仍会被使用。在构造软件系统时,如果将所有模块的源代码都静态编译到整个应用程序EXE文件中,会产生一些问题:一个缺点是增加了应用程序的大小,它会占用更多的磁盘空间,程序运行时也会消耗较大的内存空间,造成系统资源的浪费;另一个缺点是,在编写大的EXE程序时,在每次修改重建时都必须调整编译所有源代码,增加了编译过程的复杂性,也不利于阶段性的单元测试。 

  Windows系统平台上提供了一种完全不同的较有效的编程和运行环境,你可以将独立的程序模块创建为较小的DLL(Dynamic Linkable Library)文件,并可对它们单独编译和测试。在运行时,只有当EXE程序确实要调用这些DLL模块的情况下,系统才会将它们装载到内存空间中。这种 方式不仅减少了EXE文件的大小和对内存空间的需求,而且使这些DLL模块可以同时被多个应用程序使用。Microsoft Windows自己就将一些主要的系统功能以DLL模块的形式实现。例如IE中的一些基本功能就是由DLL文件实现的,它可以被其它应用程序调用和集成。

   一般来说,DLL是一种磁盘文件(通常带有DLL扩展名),它由全局数据、服务函数和资源组成,在运行时被系统加载到进程的虚拟空间中,成为调用进程的 一部分。如果与其它DLL之间没有冲突,该文件通常映射到进程虚拟空间的同一地址上。DLL模块中包含各种导出函数,用于向外界提供服务。Windows 在加载DLL模块时将进程函数调用与DLL文件的导出函数相匹配。

编写动态链接库文件时,不要有中文!动态链接库工程其实就是一套API函数(可以被外部程序使用)的集成!

动态库工程会提供让函数导出来以便其他应用、工程使用的机制。在DLL代码中,必须像下面这样明确声明导出函数:_declspec(dllexport) int MyFunction(int n);

在开发调试阶段,每次对DLL工程的更新以后,一定要将新的.lib 文件和 .dll文件重新拷贝到外部应用程序的目录下。

简述一下win32环境的DLL:
1、编写win32程序下的DLL工程,并生成解决方案,在debug目录下找到如下文件并拷贝:

#include"stdio.h"
#include"stdlib.h"

_declspec(dllexport)
int add(int a, int b)
{
	return a + b;
}
技术分享
2、另外新建项目,编写测试DLL工程:

#include"stdio.h"
#include"stdlib.h"

void main()
{
	printf("%d\n", add(5, 3));
}
把上述拷贝的文件粘贴在以上.c文件的同级目录下。

3、右键测试工程——属性——连接器——输入——

技术分享
注意:填的是.lib文件的全名,不是.dll的全名。


一个较为复杂的socketdll.c展示:(里面含有很多其他的技术细节)

#define  _CRT_SECURE_NO_WARNINGS 
#include"stdlib.h"
#include"string.h"
#include"stdio.h"

typedef struct SCK_HANDLE
{
	char version[64];
	char ip[128];
	int port;
	char *p;      //结构体套一级指针,注意内存的释放问题
	int plen;
}SCK_HANDLE;//动态库过程内部的数据类型,不想让外部上层应用测试程序
//数据类型的封装

//------------------第一套API接口---Begin--------------------------------//

//客户端初始化——获取handle上下
_declspec(dllexport)
int cltSocketInit(void **handle /*out*/)
{
	printf("cltSocketInit begin\n");
	int ret = 0;

	SCK_HANDLE *phandle=NULL;    //SCX_HANDLE是动态库工程的变量,所以要用malloc
	phandle = (SCK_HANDLE *)malloc(sizeof(SCK_HANDLE));
	if (phandle == NULL)
	{
		printf("func cltSocketInit err:%d\n",ret);
		return ret;
	}
	memset(phandle, 0, sizeof(SCK_HANDLE));    //把指针所指向的内存空间 赋值成 0;

	strcpy(phandle->ip, "192.168.1.128");
	phandle->port = 8081;

	*handle = phandle;   //间接赋值,把形参甩出去

	printf("cltSocketInit end\n");
	return 0;
}

//客户端发报文
_declspec(dllexport)
int cltSocketSend(void *handle /*in*/, unsigned char *buf /*in*/, int buflen /*in*/)
{
	int ret = 0;
	SCK_HANDLE *phandle = NULL;
	phandle = (SCK_HANDLE *)handle;

	phandle->p = (char *)malloc(buflen*sizeof(char));
	if (phandle == NULL)
	{
		ret = -1;
		printf("cltSocketSend err:%d\n", ret);
		return ret;
	}

	memcpy(phandle->p, buf, buflen);  //别人传过来的有可能不是C风格的字符串,所以按内存块拷贝
	phandle->plen = buflen;
	
	return 0;
}

//客户端收报文
_declspec(dllexport)
int cltSocketRev(void *handle /*in*/, unsigned char *buf /*in*/, int *buflen /*in out*/)
{
	int ret = 0;
	SCK_HANDLE *phandle = NULL;
	phandle = (SCK_HANDLE *)handle;


	memcpy(buf, phandle->p, phandle->plen);    //别人传过来的有可能不是C风格的字符串,所以按内存块拷贝
	buflen = phandle->plen;

	return 0;
}

//客户端释放资源
_declspec(dllexport)
int cltSocketDestory(void *handle/*in*/)
{
	int		ret = 0;
	SCK_HANDLE *hdl = NULL;
	hdl = (SCK_HANDLE *)handle;

	if (hdl->p)   //先释放指针
	{
		free(hdl->p);
	}
	free(hdl);  //再释放整个结构体

	return 0;
}

//------------------第一套api接口---End-----------------------------------//




版权声明:本文为博主原创文章,未经博主允许不得转载。

调用DLL的步骤

标签:c语言   dll   

原文地址:http://blog.csdn.net/songshimvp1/article/details/48134291

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!