鱼C论坛

 找回密码
 立即注册
查看: 2102|回复: 0

[学习笔记] 021-日志函数及第二套api函数

[复制链接]
发表于 2018-8-22 21:14:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1、日志库
        在函数出错或是调用调试时记录日志,是软件开发中的重要部分,下面是一套打印日志的函数,可以做成动态库。
        程序中存在着open()等文件操作函数,在win7 x64环境中运行不正常(日志文件不能正常生成);但业务逻辑可学习。
itcastlog.h
  1. #ifndef _ITCAST_LOG_H_
  2. #define _ITCAST_LOG_H_

  3. /*
  4. #define IC_NO_LOG_LEVEL                        0
  5. #define IC_DEBUG_LEVEL                        1
  6. #define IC_INFO_LEVEL                        2
  7. #define IC_WARNING_LEVEL                3
  8. #define IC_ERROR_LEVEL                        4;
  9. */

  10. /************************************************************************/
  11. /*
  12. const char *file:文件名称
  13. int line:文件行号
  14. int level:错误级别
  15.                 0 -- 没有日志
  16.                 1 -- debug级别
  17.                 2 -- info级别
  18.                 3 -- warning级别
  19.                 4 -- err级别
  20. int status:错误码
  21. const char *fmt:可变参数
  22. */
  23. /************************************************************************/
  24. //实际使用的Level
  25. extern int  LogLevel[5];
  26. void ITCAST_LOG(const char *file, int line, int level, int status, const char *fmt, ...);

  27. #endif
复制代码

itcastlog.c
  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <fcntl.h>
  4. #include <stdarg.h>
  5. #include <string.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <time.h>

  9. #include "ItcastLog.h"

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

  12. //Level类别
  13. #define IC_NO_LOG_LEVEL                        0
  14. #define IC_DEBUG_LEVEL                        1
  15. #define IC_INFO_LEVEL                        2
  16. #define IC_WARNING_LEVEL                3
  17. #define IC_ERROR_LEVEL                        4

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

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

  21. static int ITCAST_Error_GetCurTime(char* strTime)
  22. {
  23.         struct tm*                tmTime = NULL;
  24.         size_t                        timeLen = 0;
  25.         time_t                        tTime = 0;       
  26.        
  27.         tTime = time(NULL);
  28.         tmTime = localtime(&tTime);
  29.         //timeLen = strftime(strTime, 33, "%Y(Y)%m(M)%d(D)%H(H)%M(M)%S(S)", tmTime);
  30.         timeLen = strftime(strTime, 33, "%Y.%m.%d %H:%M:%S", tmTime);
  31.        
  32.         return timeLen;
  33. }

  34. static int ITCAST_Error_OpenFile(int* pf)
  35. {
  36.         char        fileName[1024];
  37.        
  38.         memset(fileName, 0, sizeof(fileName));
  39. #ifdef WIN32
  40.         sprintf(fileName, "c:\\itcast\\%s",ITCAST_DEBUG_FILE_);
  41.         printf("**x86**  %s\n", fileName);  // 说明我用的是x86环境
  42. #else
  43.         //sprintf(fileName, "%s/log/%s", getenv("HOME"), ITCAST_DEBUG_FILE_);
  44.         sprintf(fileName, "c:\\itcast\\%s",ITCAST_DEBUG_FILE_);
  45.         printf("**x64**  %s\n", fileName);
  46. #endif
  47.    
  48.     *pf = open(fileName, O_WRONLY|O_CREAT|O_APPEND, 0666);
  49.     if(*pf < 0)
  50.     {
  51.         return -1;
  52.     }       
  53.         return 0;
  54. }

  55. static void ITCAST_Error_Core(const char *file, int line, int level, int status, const char *fmt, va_list args)
  56. {
  57.     char str[ITCAST_MAX_STRING_LEN];
  58.     int         strLen = 0;
  59.     char tmpStr[64];
  60.     int         tmpStrLen = 0;
  61.     int  pf = 0;
  62.    
  63.     //初始化
  64.     memset(str, 0, ITCAST_MAX_STRING_LEN);
  65.     memset(tmpStr, 0, 64);
  66.    
  67.     //加入LOG时间
  68.     tmpStrLen = ITCAST_Error_GetCurTime(tmpStr);
  69.     tmpStrLen = sprintf(str, "[%s] ", tmpStr);
  70.     strLen = tmpStrLen;

  71.     //加入LOG等级
  72.     tmpStrLen = sprintf(str+strLen, "[%s] ", ICLevelName[level]);
  73.     strLen += tmpStrLen;
  74.    
  75.     //加入LOG状态
  76.     if (status != 0)
  77.     {
  78.         tmpStrLen = sprintf(str+strLen, "[ERRNO is %d] ", status);
  79.     }
  80.     else
  81.     {
  82.             tmpStrLen = sprintf(str+strLen, "[SUCCESS] ");
  83.     }
  84.     strLen += tmpStrLen;

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

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

  91.     //加入LOG发生行数
  92.     tmpStrLen = sprintf(str+strLen, " [%d]\n", line);
  93.     strLen += tmpStrLen;
  94.    
  95.     //打开LOG文件
  96.     if(ITCAST_Error_OpenFile(&pf))
  97.         {
  98.                 return ;
  99.         }
  100.        
  101.     //写入LOG文件
  102.     write(pf, str, strLen);
  103.     //IC_Log_Error_WriteFile(str);
  104.    
  105.     //关闭文件
  106.     close(pf);
  107.    
  108.     return ;
  109. }

  110. void ITCAST_LOG(const char *file, int line, int level, int status, const char *fmt, ...)
  111. {
  112.     va_list args;
  113.        
  114.         //判断是否需要写LOG
  115. //        if(level!=IC_DEBUG_LEVEL && level!=IC_INFO_LEVEL && level!=IC_WARNING_LEVEL && level!=IC_ERROR_LEVEL)
  116.         if(level == IC_NO_LOG_LEVEL)
  117.         {
  118.                 return ;
  119.         }
  120.        
  121.         //调用核心的写LOG函数
  122.     va_start(args, fmt);
  123.     ITCAST_Error_Core(file, line, level, status, fmt, args);
  124.     va_end(args);
  125.     return ;
  126. }
复制代码

2、第二套api的实现
调用该api函数
  1. // 调用第二套api函数
  2. void  main()
  3. {
  4.         int ret = 0;
  5.         void *handle = NULL;

  6.         unsigned char buf[128];
  7.         int buflen = 11;  /*in*/

  8.         unsigned char *out = NULL;
  9.         int outlen = 0;

  10.         strcpy(buf, "adddasdadddddddddasdada");
  11.         // 客户端初始化
  12.         ret = cltSocketInit2(&handle /*out*/);
  13.         // 客户端发报文
  14.         ret = cltSocketSend2(handle/*in*/, buf/*in*/, buflen/*in*/);
  15.         // 客户端收报文
  16.         ret = cltSocketRev2(handle/*in*/, &out, &outlen);
  17.         ret = cltSocketRev2_Free(&out);  //不但要把out所指向的内存空间释放,同样也把实参out赋成NULL,避免野指针
  18.         //客户端释放资源
  19.         if (handle != NULL)
  20.         {
  21.                 cltSocketDestory2(&handle/*in*/);
  22.         }

  23.         system("pause");
  24. }
复制代码

第二套api函数的源码;该源码置于第一套之后,共同做成dll文件,用于别的函数调用。
  1. //------------------第二套api接口---Begin--------------------------------//
  2. //客户端初始化 获取handle上下
  3. __declspec(dllexport)     //该语句的含义是下面的函数是向外抛出的函数
  4. int cltSocketInit2(void **handle /*out*/)
  5. {
  6.         return cltSocketInit(handle);
  7. }

  8. //客户端发报文
  9. __declspec(dllexport)
  10. int cltSocketSend2(void *handle /*in*/, unsigned char *buf /*in*/, int buflen /*in*/)
  11. {
  12.         return cltSocketSend(handle, buf, buflen);
  13. }

  14. //客户端收报文
  15. __declspec(dllexport)
  16. int cltSocketRev2(void *handle /*in*/, unsigned char **buf /*in*/, int *buflen /*in out*/)
  17. {
  18.         int ret = 0;
  19.         SCK_HANDLE *sh = NULL;
  20.         unsigned char *tmp = NULL;
  21.         if (handle == NULL || buf == NULL || buflen == NULL)
  22.         {
  23.                 ret = -1;
  24.                 printf("func cltSocketRev2 error:%d", ret);
  25.                 return ret;
  26.         }
  27.         sh = (SCK_HANDLE *)handle;

  28.         tmp = (char *)malloc(sh->buflen * sizeof(char));
  29.         if (tmp == NULL)
  30.         {
  31.                 ret = -1;
  32.                 printf("func cltSocketSend malloc error, buflen:%d", *buflen);
  33.                 return ret;
  34.         }
  35.         memcpy(tmp, sh->pbuf, sh->buflen);

  36.         *buf = tmp;
  37.         *buflen = sh->buflen;
  38.         return ret;
  39. }

  40. __declspec(dllexport)
  41. int cltSocketRev2_Free(unsigned char **buf)
  42. {
  43.         int ret = 0;
  44.         if (buf == NULL)
  45.         {
  46.                 ret = -1;
  47.                 printf("func cltSocketRev2_Free error:%d", ret);
  48.                 return ret;
  49.         }
  50.         free(*buf);
  51.         *buf = NULL;  // 释放的同时,也间接把实参修改啦

  52.         return ret;
  53. }

  54. //客户端释放资源
  55. __declspec(dllexport)
  56. int cltSocketDestory2(void **handle/*in*/)
  57. {
  58.         int ret = 0;
  59.         SCK_HANDLE *sh = NULL;
  60.         if (handle == NULL)
  61.         {
  62.                 ret = -1;
  63.                 printf("func cltSocketDestory error:%d", ret);
  64.                 return ret;
  65.         }
  66.         sh = (SCK_HANDLE *) *handle;

  67.         if (sh->pbuf != NULL)
  68.         {
  69.                 free(sh->pbuf);
  70.         }
  71.         free(sh);
  72.         *handle = NULL;  // 间接修改实参的值,避免野指针

  73.         return ret;
  74. }
  75. //------------------第二套api接口---End-----------------------------------//
复制代码


两套api函数的区别一个在主调函数中分配内存,一个在被调函数中分配内存。
另外:内存在哪里申请的的就要在哪里去释放,动态库里申请的内存就要调用动态库的函数去释放。

本帖被以下淘专辑推荐:

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-22 03:59

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表