深入理解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. 任务的运行. 这是一个生产者消费者模式,提交任务的操作是生产者,运 ...
随机推荐
- @Configuration的使用 和作用(转)
从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplic ...
- 题解 noip2019模拟赛Day1T3
题面 运河计划 问题描述 水运在人类的交通运输史中一直扮演着重要的角色.借助河流.的便利,人们得以把大量的货物输送到天南海北不仅仅是自然界现成的河流,人工开凿的运河(如苏伊士运河.巴拿马运河.我国的京 ...
- access denied
背景: 想要使用nginx转发 实现一个输出PHPinfo的页面, 比如: 访问 aaa.com/phpinfo 浏览器显示phpinfo的信息, 因为有的时候需要查看phpinfo, 所以想单独 ...
- 排列组合C、A
排列组合是组合学最基本的概念.所谓排列,就是指从给定个数的元素中取出指定个数的元素进行排序.组合则是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序. 排列组合定义及公式 排列的定义:从n个不同 ...
- trie树(字典树)的部分简单实现
什么是trie树(字典树)? trie树是一种用于快速检索的多叉树结构.和二叉查找树不同,在trie树中,每个结点上并非存储一个元素. trie树把要查找的关键词看作一个字符序列.并根据构成关键词字符 ...
- 用matlab脚本语言写M文件函数时用三种方法简单实现实现DFT(离散傅里叶变换)
%用二重循环实现DFT: function xk=dt_0(xn); %define a function N=length(xn); %caculate the length of the vari ...
- hadoop HA+Federation(高可用联邦)搭建配置(一)
hadoop HA+Federation(高可用联邦)搭建配置(一) 标签(空格分隔): 未分类 介绍 hadoop 集群一共有4种部署模式,详见<hadoop 生态圈介绍>. HA联邦模 ...
- java中判断空字符串和null的判断方法
简单总结几个方法: 1.直观的: if(s == null ||"".equals(s)); //先判断是否对象,再判断是否是空字符串 2.比较字符串长度, 效率高, 比较绕: i ...
- Postgres copy命令导入导出数据
最近有需要对数据进行迁移的需求,由于postgres性能的关系,单表3000W的数据量查询起来有一些慢,需要对大表进行切割,拆成若干个子表,涉及到原有数据要迁移到子表的需求.起初的想法是使用存储过程, ...
- JVM----Class类文件结构
JVM平台无关性 Java具有平台无关性,也就是任何操作系统都能运行Java代码.之所以能实现这一点,是因为Java运行在虚拟机之上,不同的操作系统都拥有各自的Java虚拟机,因此Java能实现“一次 ...