深入理解C语言-接口封装设计思想
断层思维
在设计时候,不需要知道实现,只需要知道如何使用
接口设计的设计思路
Sckclient客户端api模型
第一套API
(*.h)
#ifndef _SCK_CLINT_H_
#define _SCK_CLINT_H_
#ifdef __cplusplus
extern "C" {
#endif
//函数声明
// 1、客户端环境初始化
int sckClient_init(void **handle);
// 2、客户端发送报文
int sckClient_send(void *handle, unsigned char *data, int datalen);
// 3、客户端端接受报文
int sckClient_rev(void *handle, unsigned char *out, int *outlen);
// 4、客户端环境释放
int sckClient_destroy(void *handle);
#ifdef __cplusplus
}
#endif
#endif
(*.c)
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
typedef struct _SCK_HANDLE {
char version[16];
char serverip[16];
int serverport;
unsigned char *buf ;
int buflen;
}SCK_HANDLE;
//客户端初始化 获取handle上下
__declspec(dllexport)
int cltSocketInit(void **handle /*out*/)
{
int ret = 0;
SCK_HANDLE *sh = NULL;
sh = (SCK_HANDLE *)malloc(sizeof(SCK_HANDLE));
if (sh == NULL)
{
ret = -1;
printf("func cltSocketInit() err: %d, malloc err....", ret);
return ret;
}
memset(sh, 0, sizeof(SCK_HANDLE));
strcpy(sh->serverip, "192.168.0.128");
sh->serverport= 88;
*handle = sh;
return ret;
}
//客户端发报文
__declspec(dllexport)
int cltSocketSend(void *handle /*in*/, unsigned char *buf /*in*/, int buflen /*in*/)
{
int ret = 0;
SCK_HANDLE *sh = NULL;
if (handle==NULL || buf==NULL)
{
ret = -1;
printf("func cltSocketSend() err: %d, (handle==NULL || buf==NULL)", ret);
return ret;
}
sh = (SCK_HANDLE *)handle ;
sh->buf = (char *)malloc(buflen);
if (sh->buf == NULL)
{
ret = -2;
printf("func cltSocketSend() err: %d, (buflen:%d)", ret, buflen);
return ret;
}
memcpy(sh->buf, buf, buflen);
sh->buflen = buflen;
return ret;
}
//客户端收报文
__declspec(dllexport)
int cltSocketRev(void *handle /*in*/, unsigned char *buf /*in*/, int *buflen /*in out*/)
{
int ret = 0;
SCK_HANDLE *sh = NULL;
if (handle==NULL || buf==NULL || buflen==NULL)
{
ret = -1;
printf("func cltSocketSend() err: %d, ((handle==NULL || buf==NULL || buflen==NULL))", ret);
return ret;
}
sh = (SCK_HANDLE *)handle;
memcpy(buf, sh->buf, sh->buflen);
*buflen = sh->buflen;
if (sh->buf != NULL)
{
free(sh->buf);
sh->buf = NULL; //把状态回到原始
sh->buflen = 0;
}
return ret;
}
//客户端释放资源
__declspec(dllexport)
int cltSocketDestory(void *handle/*in*/)
{
int ret = 0;
SCK_HANDLE *sh = NULL;
if (handle==NULL )
{
ret = -1;
printf("func cltSocketSend() err: %d, ((handle==NULL )", ret);
return ret;
}
sh = (SCK_HANDLE *)handle;
if (sh->buf != NULL)
{
free(sh->buf);
sh->buf = NULL;
sh->buflen = 0;
}
free(sh);
return ret;
}
第二套API
(*.h)
#ifndef _SCK_CLINT02_H_
#define _SCK_CLINT02_H_
#ifdef __cplusplus
extern "C" {
#endif
//函数声明
// 1、客户端环境初始化
int sckClient_init2(void **handle);
// 2、客户端发送报文
int sckClient_send2(void *handle, unsigned char *data, int datalen);
// 3、客户端端接受报文
int sckClient_rev2(void *handle, unsigned char **out, int *outlen);
int sckClient_rev2_Free(void **p);
// 4、客户端环境释放
int sckClient_destroy2(void **handle);
#ifdef __cplusplus
}
#endif
#endif
(*.c)
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
typedef struct _SCK_HANDLE {
char version[16];
char serverip[16];
int serverport;
unsigned char *buf ;
int buflen;
}SCK_HANDLE;
//客户端环境初始化
__declspec(dllexport)
int cltSocketInit2(void **handle)
{
return cltSocketInit(handle /*out*/);
}
//客户端发报文
__declspec(dllexport)
int cltSocketSend2(void *handle, unsigned char *buf, int buflen)
{
return cltSocketSend(handle /*in*/, buf /*in*/, buflen /*in*/);
}
//客户端收报文
__declspec(dllexport)
int cltSocketRev2(void *handle, unsigned char **buf, int *buflen)
{
int ret = 0;
SCK_HANDLE *sh = NULL;
if (handle==NULL || buf==NULL || buflen==NULL)
{
ret = -1;
ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, "func cltSocketRev2() err: %d, (handle==NULL || buf==NULL || buflen==NULL)", ret);
return ret;
}
sh = (SCK_HANDLE *)handle;
*buf = (char *)malloc( sh->buflen);
memcpy(*buf, sh->buf, sh->buflen);
*buflen = sh->buflen;
return ret;
}
__declspec(dllexport)
int cltSocketRev2_Free(unsigned char **buf)
{
if (buf == NULL)
{
return -1;
}
free(*buf);
*buf = NULL;
return 0;
}
//客户端释放资源
__declspec(dllexport)
int cltSocketDestory2(void **handle)
{
int ret = 0;
SCK_HANDLE *sh = NULL;
if (handle==NULL )
{
ret = -1;
ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, "func cltSocketSend() err: %d, ((handle==NULL )", ret);
return ret;
}
sh = (SCK_HANDLE *)*handle;
if (sh->buf != NULL)
{
free(sh->buf);
sh->buf = NULL;
sh->buflen = 0;
}
free(sh);
*handle = NULL; //把实参赋值null
return ret;
}
日志打印
(*.h)
#ifndef __LOG_H_
#define __LOG_H_
/***********************************************************************
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 LOG(const char *file, int line, int level, int status, const char *fmt, ...);
#endif
(*.c)
#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 "Log.h"
#define DEBUG_FILE_ "error.log"
#define MAX_STRING_LEN 10240
//日志输出目录
#define FILE_SPACE "c:/log/%s"
//Level类别
#define NO_LOG_LEVEL 0
#define DEBUG_LEVEL 1
#define INFO_LEVEL 2
#define WARNING_LEVEL 3
#define ERROR_LEVEL 4
//日志等级
int LogLevel[5] = { NO_LOG_LEVEL, DEBUG_LEVEL, INFO_LEVEL, WARNING_LEVEL, ERROR_LEVEL };
//Level的名称
char LevelName[5][10] = { "NOLOG", "DEBUG", "INFO", "WARNING", "ERROR" };
static int 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 Error_OpenFile(int* pf)
{
char fileName[1024];
memset(fileName, 0, sizeof(fileName));
#ifdef WIN32
sprintf(fileName, FILE_SPACE, DEBUG_FILE_);
#else
sprintf(fileName, FILE_SPACE, DEBUG_FILE_);
//sprintf(fileName, "%s/log/%s", getenv("HOME"), DEBUG_FILE_);
#endif
*pf = open(fileName, O_WRONLY | O_CREAT | O_APPEND, 0666);
if (*pf < 0)
{
return -1;
}
return 0;
}
static void Error_Core(const char *file, int line, int level, int status, const char *fmt, va_list args)
{
char str[MAX_STRING_LEN];
int strLen = 0;
char tmpStr[64];
int tmpStrLen = 0;
int pf = 0;
//初始化
memset(str, 0, MAX_STRING_LEN);
memset(tmpStr, 0, 64);
//加入LOG时间
tmpStrLen = Error_GetCurTime(tmpStr);
tmpStrLen = sprintf(str, "[%s] ", tmpStr);
strLen = tmpStrLen;
//加入LOG等级
tmpStrLen = sprintf(str + strLen, "[%s] ", LevelName[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 (Error_OpenFile(&pf))
{
return;
}
//写入LOG文件
write(pf, str, strLen);
//Log_Error_WriteFile(str);
//关闭文件
close(pf);
return;
}
void LOG(const char *file, int line, int level, int status, const char *fmt, ...)
{
va_list args;
//判断是否需要写LOG
// if(level!=DEBUG_LEVEL && level!=INFO_LEVEL && level!=WARNING_LEVEL && level!=ERROR_LEVEL)
if (level == NO_LOG_LEVEL)
{
return;
}
//调用核心的写LOG函数
va_start(args, fmt);
Error_Core(file, line, level, status, fmt, args);
va_end(args);
return;
}
深入理解C语言-接口封装设计思想的更多相关文章
- MapReduce原理与设计思想
简单解释 MapReduce 算法 一个有趣的例子 你想数出一摞牌中有多少张黑桃.直观方式是一张一张检查并且数出有多少张是黑桃? MapReduce方法则是: 给在座的所有玩家中分配这摞牌 让每个玩家 ...
- 大数据 --> MapReduce原理与设计思想
MapReduce原理与设计思想 简单解释 MapReduce 算法 一个有趣的例子:你想数出一摞牌中有多少张黑桃.直观方式是一张一张检查并且数出有多少张是黑桃? MapReduce方法则是: 给在座 ...
- php命名空间的设计思想和缺点
相比C#等语言,你可以在PHP函数里面随意定义变量并赋值,而不用担心覆盖了全局变量,或者类变量:你也可以随意的定义类变量,而不用担心会和函数名冲突,因为变量前面都有个$. php的命名空间和全局变量. ...
- 转:MapReduce原理与设计思想
转自:http://www.cnblogs.com/wuyudong/p/mapreduce-principle.html 简单解释 MapReduce 算法 一个有趣的例子 你想数出一摞牌中有多少张 ...
- Day1:了解APICloud平台、理解APICloud应用设计思想、掌握平台使用流程。学习如何对一款APP进行需求分析、功能分解和架构设计等编码之前重要的准备工作
学习目标 总体上了解一下APICloud平台,重点介绍相关的学习资源,入门资料,常见的FAQ等 明确我们这七天要开发一个什么样的APP,明确功能需求,跟上每天的课程节奏,可以课前预习 梳理出对于一款A ...
- 透彻理解Spring事务设计思想之手写实现
前言 事务,是描述一组操作的抽象,比如对数据库的一组操作,要么全部成功,要么全部失败.事务具有4个特性:Atomicity(原子性),Consistency(一致性),Isolation(隔离性),D ...
- 《深入理解Android内核设计思想》
<深入理解Android内核设计思想> 基本信息 作者: 林学森 出版社:人民邮电出版社 ISBN:9787115348418 上架时间:2014-4-25 出版日期:2014 年5月 开 ...
- 透彻理解Spring事务设计思想之手写实现(山东数漫江湖)
前言 事务,是描述一组操作的抽象,比如对数据库的一组操作,要么全部成功,要么全部失败.事务具有4个特性:Atomicity(原子性),Consistency(一致性),Isolation(隔离性),D ...
- 聊聊高并发(三十八)解析java.util.concurrent各个组件(十四) 理解Executor接口的设计
JUC包中除了一系列的同步类之外,就是Executor运行框架相关的类.对于一个运行框架来说,能够分为两部分 1. 任务的提交 2. 任务的运行. 这是一个生产者消费者模式,提交任务的操作是生产者,运 ...
随机推荐
- django-cookies设置与使用
原文地址:http://www.cnblogs.com/wupeiqi/articles/5246483.html 感谢说话声音像评书表演艺术家刘兰芳老师的武沛齐老师的倾力奉献! 1.获取Cookie ...
- BZOJ 2049: [Sdoi2008]Cave 洞穴勘测 (LCT维护连通性)
直接把x设为根,然后查询y所在联通块的根是不是x就行了. CODE #include <cstdio> #include <cstring> #include <algo ...
- vue项目实现详情页后退缓存之前的数据
vue项目实现详情页后退缓存之前的数据 2019年02月19日 14:54:57 不想写代码的程序员 阅读数:244 一.需要缓存的内容: 1.后退缓存条件查询的数据 2.后退缓存分页信息 二.实 ...
- Hdu 1247 Hat's Words(Trie树)
Hat's Words Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- 【luoguP1311 】选择客栈
题目描述 丽江河边有nn家很有特色的客栈,客栈按照其位置顺序从 11到nn编号.每家客栈都按照某一种色调进行装饰(总共 kk 种,用整数 00 ~k-1k−1 表示),且每家客栈都设有一家咖啡店,每家 ...
- 关于phoenix构建hbase视图,更新hbase表后,视图表是否更新的验证
1:创建表 create 'MY_TABLE', 'CF1','CF2' 2:在hbase上插入一条数据 put ' ,'CF1:V1', 'uwo1' 3:在phoenix上创建视图 create ...
- ARTS打卡计划第十一周
Algorithms: https://leetcode-cn.com/problems/linked-list-cycle/ 链表环. Review: “What I learned from do ...
- Android局部更新(RecyclerView+ DiffUtil)
一 概述 DiffUtil是support-v7:24.2.0中的新工具类,它用来比较两个数据集,寻找出旧数据集->新数据集的最小变化量. 说到数据集,相信大家知道它是和谁相关的了,就是我的最爱 ...
- Android蓝牙开发技术学习总结
Android开发,提供对蓝牙的通讯栈的支持,允许设别和其他的设备进行无线传输数据.应用程序层通过安卓API来调用蓝牙的相关功能,这些API使程序无线连接到蓝牙设备,并拥有P2P或者多端无线连接的特性 ...
- 用JSON文本动态创建DataGrid
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...