C语言动态库的使用

受限创建一个win32的控制台DLL项目,添加.c文件和.h文件,需要导出的接口
#include "stdlib.h"
#include "stdio.h"
#include "string.h"



typedef struct _SCK_HANDLE {
	char	version[16];
	char	serverip[16];
	int		serverport;
	char    *pBuf;
	int		buflen ;
}SCK_HANDLE;



//------------------第一套api接口---Begin--------------------------------//
//客户端初始化 获取handle上下
__declspec(dllexport)
int cltSocketInit(void **handle /*out*/)
{
	SCK_HANDLE* sh = (SCK_HANDLE*)malloc(sizeof(SCK_HANDLE));
	if (!sh)
	{
		return -1;
	}

	

	strcpy(sh->version, "1.0.0");
	strcpy(sh->serverip, "192.168.0.100");
	sh->serverport = 8080;
	*handle = sh;
	return 1;
}

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

	if (!handle || !buf)
	{
		return -1;
	}
	sh = (SCK_HANDLE*)handle;
	sh->pBuf = (char *)malloc(buflen * sizeof(char));

	if (!sh->pBuf)
	{
		return -1;
	}

	memcpy(sh->pBuf, buf, buflen);
	sh->buflen = buflen;

	return 1;
}

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

	if (!handle || !buf)
	{
		return -1;
	}
	sh = (SCK_HANDLE*)handle;
	if (!sh->pBuf)
	{
		return -1;
	}
	
	memcpy(buf, sh->pBuf, sh->buflen);
	*buflen = sh->buflen;

	return 1;
}

//客户端释放资源
__declspec(dllexport)
int cltSocketDestory(void *handle/*in*/)
{
	SCK_HANDLE* sh = NULL;

	if (!handle)
	{
		return 1;
	}

	sh = (SCK_HANDLE*)handle;

	if (sh->pBuf)
	{
		free(sh->pBuf);
	}
	free(sh);

	return 1;
}
//------------------第一套api接口---End-----------------------------------//


//------------------第二套api接口---Begin--------------------------------//
__declspec(dllexport)
int cltSocketInit2(void **handle)
{
	return cltSocketInit(handle);
}

//客户端发报文
__declspec(dllexport)
int cltSocketSend2(void *handle, unsigned char *buf,  int buflen)
{
	return cltSocketSend(handle, buf, buflen);
}
//客户端收报文
__declspec(dllexport)
int cltSocketRev2(void *handle, unsigned char **buf, int *buflen)
{
	SCK_HANDLE* sh = NULL;
	unsigned char* bufTmp = NULL;

	if (!handle || !buf)
	{
		return -1;
	}
	sh = (SCK_HANDLE*)handle;
	if (!sh->pBuf)
	{
		return -1;
	}
	bufTmp = (char*)malloc(sh->buflen * sizeof(char));
	if (!bufTmp)
	{
		return -1;
	}

	strcpy(bufTmp, sh->pBuf);
	*buf = bufTmp;
	*buflen = sh->buflen;
	
	return 1;
}
int cltSocketRev2_Free(unsigned char **buf)
{
	if (buf == NULL)
	{
		return -1;
	}
	free(*buf);
	*buf = NULL; //间接的把实参给修改了
	return 1;
}
//客户端释放资源
__declspec(dllexport)
int cltSocketDestory2(void **handle)
{
	int ret = 0;
	SCK_HANDLE *sh = NULL;
	if (handle == NULL)
	{
		return -1;
	}

	sh = (SCK_HANDLE *) *handle;

	if (sh->pBuf != NULL)
	{
		free(sh->pBuf);
	}

	free(sh);
	*handle = NULL; //间接修改实参的值 避免野指针
	return 1;
}
//------------------第二套api接口---End--------------------------------//


#ifndef _INC_Demo01_H
#define _INC_Demo01_H

#ifdef __cplusplus    //__cplusplus是cpp中自定义的一个宏
extern "C" {          //告诉编译器,这部分代码按C语言的格式进行编译,而不是C++的
#endif
	//------------------第一套api接口---Begin--------------------------------//
	//客户端初始化 获取handle上下
	int cltSocketInit(void **handle /*out*/); 
	
	//客户端发报文
	int cltSocketSend(void *handle /*in*/, unsigned char *buf /*in*/,  int buflen /*in*/);
	
	//客户端收报文
	int cltSocketRev(void *handle /*in*/, unsigned char *buf /*in*/, int *buflen /*in out*/);
	
	//客户端释放资源
	int cltSocketDestory(void *handle/*in*/);
	//------------------第一套api接口---End-----------------------------------//
	
	
	//------------------第二套api接口---Begin--------------------------------//
	int cltSocketInit2(void **handle); 

	//客户端发报文
	int cltSocketSend2(void *handle, unsigned char *buf,  int buflen);
	//客户端收报文
	int cltSocketRev2(void *handle, unsigned char **buf, int *buflen);
	int cltSocketRev2_Free(unsigned char **buf);
	//客户端释放资源

	int cltSocketDestory2(void **handle);
	//------------------第二套api接口---End--------------------------------//
#ifdef  __cplusplus
}
#endif

#endif  /* _INC_Demo01_H */


注意,__declspec(dllexport)这个声明是告诉编译器该函数是要导出函数,没有这个声明在lib中是不会生成对应接口的,在别的工程中也就不能够调用


该dll编译完成后需要将dll,lib和.h文件拷贝到你的主调用的工程中,然后在项目属性的项目依赖里面添加lib依赖即可调用接口。

#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "socketclientdll.h"

int main1()
{
	void *handle = NULL;
	int resul = -1;
	
	unsigned char buf[128];
	int inBufLen = 11;

	unsigned char outbuf[128];
	int outBufLen = 11;

	strcpy(buf, "ddddddddddd");


	//客户端初始化 获取handle上下
	resul = cltSocketInit(&handle /*out*/);

	if (resul != 1)
	{
		goto End;
	}

	//客户端发报文
	resul = cltSocketSend(handle /*in*/, buf /*in*/,  inBufLen /*in*/);

	if (resul != 1)
	{
		goto End;
	}

	//客户端收报文
	resul = cltSocketRev(handle /*in*/, outbuf /*in*/, &outBufLen /*in out*/);

	if (resul != 1)
	{
		goto End;
	}

	//客户端释放资源
	End:
	if (handle)
	{
		cltSocketDestory(handle/*in*/);
	}
	
	return 0;
}

int main2()
{
	void *handle = NULL;
	int resul = -1;

	unsigned char buf[128];
	int inBufLen = 11;

	unsigned char* outbuf = NULL;
	int outBufLen = 11;

	strcpy(buf, "ddddddddddd");


	//客户端初始化 获取handle上下
	resul = cltSocketInit2(&handle /*out*/);

	if (resul != 1)
	{
		goto End;
	}

	//客户端发报文
	resul = cltSocketSend2(handle /*in*/, buf /*in*/,  inBufLen /*in*/);

	if (resul != 1)
	{
		goto End;
	}

	//客户端收报文
	resul = cltSocketRev2(handle /*in*/, &outbuf /*in*/, &outBufLen /*in out*/);

	if (resul != 1)
	{
		goto End;
	}

	//客户端释放资源
End:
	if (handle)
	{
		cltSocketDestory2(&handle/*in*/);
	}

	return 0;
}

可以为dll添加错误日志处理,可参考如下

//written by wangbaoming1999@163.com
//20140323
//itcastlog.h 日志头文件


#ifndef _ITCAST_LOG_H_
#define _ITCAST_LOG_H_

/*
#define IC_NO_LOG_LEVEL			0
#define IC_DEBUG_LEVEL			1
#define IC_INFO_LEVEL			2
#define IC_WARNING_LEVEL		3
#define IC_ERROR_LEVEL			4;
*/

/************************************************************************/
/* 
const char *file:文件名称
int line:文件行号
int level:错误级别
		0 -- 没有日志
		1 -- debug级别
		2 -- info级别
		3 -- warning级别
		4 -- err级别
int status:错误码
const char *fmt:可变参数
*/
/************************************************************************/
//实际使用的Level
extern int  LogLevel[5];
void ITCAST_LOG(const char *file, int line, int level, int status, const char *fmt, ...);

#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "ItcastLog.h"

#define ITCAST_DEBUG_FILE_	"socketclient.log"
#define ITCAST_MAX_STRING_LEN 		10240

//Level类别
#define IC_NO_LOG_LEVEL			0
#define IC_DEBUG_LEVEL			1
#define IC_INFO_LEVEL			2
#define IC_WARNING_LEVEL		3
#define IC_ERROR_LEVEL			4

int  LogLevel[5] = {IC_NO_LOG_LEVEL, IC_DEBUG_LEVEL, IC_INFO_LEVEL, IC_WARNING_LEVEL, IC_ERROR_LEVEL};

//Level的名称
char ICLevelName[5][10] = {"NOLOG", "DEBUG", "INFO", "WARNING", "ERROR"};

static int ITCAST_Error_GetCurTime(char* strTime)
{
	struct tm*		tmTime = NULL;
	size_t			timeLen = 0;
	time_t			tTime = 0;	
	
	tTime = time(NULL);
	tmTime = localtime(&tTime);
	//timeLen = strftime(strTime, 33, "%Y(Y)%m(M)%d(D)%H(H)%M(M)%S(S)", tmTime);
	timeLen = strftime(strTime, 33, "%Y.%m.%d %H:%M:%S", tmTime);
	
	return timeLen;
}

static int ITCAST_Error_OpenFile(int* pf)
{
	char	fileName[1024];
	
	memset(fileName, 0, sizeof(fileName));
#ifdef WIN32
	sprintf(fileName, "c:\\itcast\\%s",ITCAST_DEBUG_FILE_);
#else
	//sprintf(fileName, "%s/log/%s", getenv("HOME"), ITCAST_DEBUG_FILE_);
	sprintf(fileName, "c:\\itcast\\%s",ITCAST_DEBUG_FILE_);
#endif
    
    *pf = open(fileName, O_WRONLY|O_CREAT|O_APPEND, 0666);
    if(*pf < 0)
    {
        return -1;
    }
	
	return 0;
}

static void ITCAST_Error_Core(const char *file, int line, int level, int status, const char *fmt, va_list args)
{
    char str[ITCAST_MAX_STRING_LEN];
    int	 strLen = 0;
    char tmpStr[64];
    int	 tmpStrLen = 0;
    int  pf = 0;
    
    //初始化
    memset(str, 0, ITCAST_MAX_STRING_LEN);
    memset(tmpStr, 0, 64);
    
    //加入LOG时间
    tmpStrLen = ITCAST_Error_GetCurTime(tmpStr);
    tmpStrLen = sprintf(str, "[%s] ", tmpStr);
    strLen = tmpStrLen;

    //加入LOG等级
    tmpStrLen = sprintf(str+strLen, "[%s] ", ICLevelName[level]);
    strLen += tmpStrLen;
    
    //加入LOG状态
    if (status != 0) 
    {
        tmpStrLen = sprintf(str+strLen, "[ERRNO is %d] ", status);
    }
    else
    {
    	tmpStrLen = sprintf(str+strLen, "[SUCCESS] ");
    }
    strLen += tmpStrLen;

    //加入LOG信息
    tmpStrLen = vsprintf(str+strLen, fmt, args);
    strLen += tmpStrLen;

    //加入LOG发生文件
    tmpStrLen = sprintf(str+strLen, " [%s]", file);
    strLen += tmpStrLen;

    //加入LOG发生行数
    tmpStrLen = sprintf(str+strLen, " [%d]\n", line);
    strLen += tmpStrLen;
    
    //打开LOG文件
    if(ITCAST_Error_OpenFile(&pf))
	{
		return ;
	}
	
    //写入LOG文件
    write(pf, str, strLen);
    //IC_Log_Error_WriteFile(str);
    
    //关闭文件
    close(pf);
    
    return ;
}


void ITCAST_LOG(const char *file, int line, int level, int status, const char *fmt, ...)
{
    va_list args;
	
	//判断是否需要写LOG
//	if(level!=IC_DEBUG_LEVEL && level!=IC_INFO_LEVEL && level!=IC_WARNING_LEVEL && level!=IC_ERROR_LEVEL)
	if(level == IC_NO_LOG_LEVEL)
	{
		return ;
	}
	
	//调用核心的写LOG函数
    va_start(args, fmt);
    ITCAST_Error_Core(file, line, level, status, fmt, args);
    va_end(args);
    
    return ;
}

添加日志的时候可以这样调用ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], 4, "func cltSocketInit() err:%d", ret);

__FILE__和 __LINE__是编译器提供的两个宏定义可以定位当前文件和当前行,具体的可以问百度


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值