服务器开发27:log4c充当服务器跨平台日志库(cmake跨平台编译,配置介绍及代码封装)

本文详细介绍了如何在不同平台上编译expat和log4c,并对比了log4cpp与log4c的区别。重点讲解了log4c的基本概念、配置文件示例和代码使用案例,包括C/C++封装实例与配置管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、跨平台编译

1)编译准备

(1)expat编译
  • linux编译
    传送门
  • win编译
    1)下载
    https://libexpat.github.io/
    https://github.com/libexpat/libexpat/releases
    2)将下载的源码文件“libexpat-R_2_4_4.zip”解压之后,
    由于源码文件里已经提供了CMakeLists.txt,所有直接使用cmake加载脚本构建生成VS工程文件。
    在这里插入图片描述
    3)方法2:使用大家常用的cmake的命令行操作,如下:
## 1、打开源代码文件夹
cd C:\Users\tomcat\Desktop\libexpat-R_2_4_4\expat
## 2、新建编译输出文件夹
mkdir build
## 3、进入编译输出文件夹
cd build
## 4、生成.sln工程文件
cmake ..
## 5、编译代码
cmake --build .

4)编译完毕之后,生成的dll和lib文件如下:
在这里插入图片描述

2)原生linux编译、安装

  • 下载位置
    http://log4c.sourceforge.net/

  • 编译安装指令

$ gzip -dc log4c-1.2.4.tar.gz | tar tvf -
$ cd log4c-1.2.4/
$ ./configure --enable-static --prefix=/home/ww/ww/gitlabproject/opcodetester/third/log4c-install/ CC="gcc -m32"
$ make
$ make install

3)cmake跨平台编译

  • 第三方库expat的相关编译好的文件放进来,如下:
    在这里插入图片描述在这里插入图片描述
  • 编写测试案例
    编写一个简单的测试文件“ConsoleApplication1.cpp”,放在log4c文件夹里的examples子文件夹里。
    在这里插入图片描述
  • ConsoleApplication1.cpp:
#include <iostream>
#include "log4c.h"

#ifdef _DEBUG
#pragma comment(lib, "..\\lib\\Win32\\Debug\\log4cd.lib")
#else
#pragma comment(lib, "..\\lib\\Win32\\Release\\log4c.lib")
#endif

int main()
{
    std::cout << "Hello World!\n";
	log4c_init();

	log4c_category_t* mylog = log4c_category_get("framework");
	log4c_category_log(mylog, LOG4C_PRIORITY_DEBUG, "Hello World!");

	log4c_category_t* mycat = NULL;
	mycat = log4c_category_get("six13log.log.app.application2");

	log4c_category_log(mycat, LOG4C_PRIORITY_DEBUG, "Debugging app 2");
	log4c_category_log(mycat, LOG4C_PRIORITY_ERROR,
		"some error from app2 at line %d in file %s",
		__LINE__, __FILE__);

	log4c_fini();
}

  • 新建文件config.h
    将log4c子文件夹src里面的“config.h.in”文件,复制出一份,改名为config.h。
    通过将config.h内容修改如下:
/* src/config.h.in.  Generated from configure.in by autoheader.  */

/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
   systems. This function is required for `alloca.c' support on those systems.
   */
#undef CRAY_STACKSEG_END

/* Define to 1 if using `alloca.c'. */
#undef C_ALLOCA

/* Define to 1 if you have `alloca', as a function or macro. */
#undef HAVE_ALLOCA

/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
   */
#undef HAVE_ALLOCA_H

/* Define to 1 if you have the <alloc.h> header file. */
#undef HAVE_ALLOC_H

/* Define to 1 if you have the declaration of `gmtime_r', and to 0 if you
   don't. */
#undef HAVE_DECL_GMTIME_R

/* Define to 1 if you have the declaration of `localtime_r', and to 0 if you
   don't. */
#undef HAVE_DECL_LOCALTIME_R

/* Define to 1 if you have the declaration of `sleep', and to 0 if you don't.
   */
#undef HAVE_DECL_SLEEP

/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H

/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
#undef HAVE_DOPRNT

/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H

/* Define to 1 if you have the `gethostname' function. */
#undef HAVE_GETHOSTNAME

/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H

/* Define to 1 if you have the `getpagesize' function. */
#undef HAVE_GETPAGESIZE

/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY

/* Define to 1 if you have the `gmtime_r' function. */
#undef HAVE_GMTIME_R

/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H

/* Define to 1 if you have the <langinfo.h> header file. */
#undef HAVE_LANGINFO_H

/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H

/* Define to 1 if you have the `localtime_r' function. */
#undef HAVE_LOCALTIME_R

/* Define to 1 if you have the <malloc.h> header file. */
//#undef HAVE_MALLOC_H
#define HAVE_MALLOC_H

/* Define to 1 if you have the <memory.h> header file. */
//#undef HAVE_MEMORY_H

/* Define to 1 if you have the `memset' function. */
//#undef HAVE_MEMSET

/* Define to 1 if you have a working `mmap' system call. */
#undef HAVE_MMAP

/* Define to 1 if you have the `munmap' function. */
#undef HAVE_MUNMAP

/* Define to 1 if you have the `nl_langinfo' function. */
#undef HAVE_NL_LANGINFO

/* Define to 1 if you have the <pthread.h> header file. */
#undef HAVE_PTHREAD_H

/* Define to 1 if you have the `sbrk' function. */
#undef HAVE_SBRK

/* Define to 1 if you have the `sleep' function. */
#undef HAVE_SLEEP

/* Define to 1 if you have the <stdarg.h> header file. */
//#undef HAVE_STDARG_H
#define HAVE_STDARG_H

/* Define to 1 if you have the <stddef.h> header file. */
//#undef HAVE_STDDEF_H
#define HAVE_STDDEF_H

/* Define to 1 if you have the <stdint.h> header file. */
//#undef HAVE_STDINT_H
#define HAVE_STDINT_H

/* Define to 1 if you have the <stdlib.h> header file. */
//#undef HAVE_STDLIB_H
#define HAVE_STDLIB_H

/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP

/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR

/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H

/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H

/* Define to 1 if you have the `strncasecmp' function. */
#undef HAVE_STRNCASECMP

/* Define to 1 if you have the `strrchr' function. */
#undef HAVE_STRRCHR

/* Define to 1 if you have the `strstr' function. */
#undef HAVE_STRSTR

/* Define to 1 if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H

/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H

/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H

/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H

/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H

/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H

/* Define to 1 if you have the `utime' function. */
#undef HAVE_UTIME

/* Define to 1 if you have the <utime.h> header file. */
#undef HAVE_UTIME_H

/* Define to 1 if `utime(file, NULL)' sets file's timestamp to the present. */
#undef HAVE_UTIME_NULL

/* Define to 1 if you have the <varargs.h> header file. */
#undef HAVE_VARARGS_H

/* Define to 1 if you have the `vprintf' function. */
#undef HAVE_VPRINTF

/* Define to the sub-directory in which libtool stores uninstalled libraries.
   */
#undef LT_OBJDIR

/* Name of package */
#undef PACKAGE

/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT

/* Define to the full name of this package. */
#undef PACKAGE_NAME

/* Define to the full name and version of this package. */
#undef PACKAGE_STRING

/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME

/* Define to the home page for this package. */
#undef PACKAGE_URL

/* Define to the version of this package. */
#undef PACKAGE_VERSION

/* If using the C implementation of alloca, define if you know the
   direction of stack growth for your system; otherwise it will be
   automatically deduced at runtime.
	STACK_DIRECTION > 0 => grows toward higher addresses
	STACK_DIRECTION < 0 => grows toward lower addresses
	STACK_DIRECTION = 0 => direction of growth unknown */
#undef STACK_DIRECTION

/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS

/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME

/* Define to 1 if your <sys/time.h> declares `struct tm'. */
#undef TM_IN_SYS_TIME

/* Version number of package */
//#undef VERSION
#define VERSION "1.2.4"
#define LOG4C_RCPATH "d:"

/* build log4c with initialization constructors */
#undef WITH_CONSTRUCTORS

/* Define if we found pthread.h libpthread */
#undef WITH_ROLLINGFILE

/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
   `char[]'. */
#undef YYTEXT_POINTER

/* "POSIXandGNU extensions" */
#undef _GNU_SOURCE

/* Enable automatic reread of log4crc file */
#undef __ENABLE_REREAD__

/* Define to empty if `const' does not conform to ANSI C. */
#undef const

/* Define to `__inline__' or `__inline' if that's what the C compiler
   calls it, or to nothing if 'inline' is not supported under any name.  */
#ifndef __cplusplus
#undef inline
#endif

/* Define to `unsigned int' if <sys/types.h> does not define. */
//#undef size_t

/* Trying to use __va_copy on non-C89 systems */
//#undef va_copy


  • 编写cmake
    在log4c-1.2.4里面创建CMakeLists.txt
cmake_minimum_required (VERSION 2.8.12) //可以写高点版本
project (log4c)                         //定义项目名字

# add flag
add_definitions(-DHAVE_CONFIG_H)            //-D定义宏HAVE_CONFIG_H
add_definitions(-D_CRT_SECURE_NO_WARNINGS)  //去除warning警告

# add var
set(CMAKE_DEBUG_POSTFIX d)
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
    set(ARCH_POSTFIX "Win32")
else()
    set(ARCH_POSTFIX x64)
endif()


IF (CMAKE_BUILD_TYPE MATCHES "Release")
    SET(CMAKE_BUILD_POSTFIX "${CMAKE_RELEASE_POSTFIX}")
ELSEIF (CMAKE_BUILD_TYPE MATCHES "MinSizeRel")
    SET(CMAKE_BUILD_POSTFIX "${CMAKE_MINSIZEREL_POSTFIX}")
ELSEIF(CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
    SET(CMAKE_BUILD_POSTFIX "${CMAKE_RELWITHDEBINFO_POSTFIX}")
ELSEIF(CMAKE_BUILD_TYPE MATCHES "Debug")
    SET(CMAKE_BUILD_POSTFIX "${CMAKE_DEBUG_POSTFIX}")
ELSE()
    SET(CMAKE_BUILD_POSTFIX "")
ENDIF()

# add .c and .cpp
include_directories (./src ./src/log4c ./src/sd )
aux_source_directory (./src/log4c DIR_SRCS1)
aux_source_directory (./src/sd DIR_SRCS2)
list(REMOVE_ITEM DIR_SRCS1 "./src/log4c/appender_type_mmap.c") 
list(REMOVE_ITEM DIR_SRCS1 "./src/log4c/appender_type_mmap.h")  
list(REMOVE_ITEM DIR_SRCS1 "./src/log4c/appender_type_mmap.h")  
list(REMOVE_ITEM DIR_SRCS2 "./src/sd/sprintf.osf.c")  
list(REMOVE_ITEM DIR_SRCS2 "./src/sd/domnode.c")  

# add link dir
link_directories("./libexpat-R_2_4_4/lib/${ARCH_POSTFIX}")

# create dll(project1) or lib(project2)
add_library (log4c_shared SHARED ${DIR_SRCS1} ${DIR_SRCS2})
add_library (log4c_static STATIC ${DIR_SRCS1} ${DIR_SRCS2})
set_target_properties (log4c_shared PROPERTIES OUTPUT_NAME "log4c")
set_target_properties (log4c_static PROPERTIES OUTPUT_NAME "log4c_static")
set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib/${ARCH_POSTFIX})
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/${ARCH_POSTFIX})
target_compile_definitions( log4c_shared PRIVATE LOG4C_EXPORTS )
target_compile_definitions( log4c_static PRIVATE LOG4C_EXPORTS )

# add libexpat library
list(APPEND EXTRA_LIBS libexpat)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/libexpat-R_2_4_4/include")
target_link_libraries(log4c_shared PUBLIC ${EXTRA_LIBS})
target_include_directories(log4c_shared PUBLIC "${PROJECT_BINARY_DIR}" ${EXTRA_INCLUDES})
target_link_libraries(log4c_static PUBLIC ${EXTRA_LIBS})
target_include_directories(log4c_static PUBLIC "${PROJECT_BINARY_DIR}" ${EXTRA_INCLUDES})

# create project3
add_executable(test ./examples/ConsoleApplication1.cpp)

  • 这里用到的配置文件
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE log4c SYSTEM "">

<log4c version="1.2.4">

	<config>
		<bufsize>0</bufsize>
		<debug level="2"/>
		<nocleanup>0</nocleanup>
		<reread>1</reread>
	</config>

	<category name="root" priority="notice"/>
    <category name="six13log.log" priority="error" appender="stdout" />

	<rollingpolicy name="myrollingpolicy" type="sizewin" maxsize="1024" maxnum="10" />

	<appender name="myrollingfileappender" type="rollingfile" logdir="." prefix="myprefix" layout="dated" rollingpolicy="myrollingpolicy" />
	
	<appender name="stdout" type="stream" layout="basic"/>
	<appender name="stderr" type="stream" layout="dated"/>
	<appender name="syslog" type="syslog" layout="basic"/>

	<appender name="s13file" type="s13_file" layout="basic"/>
	<appender name="plain_stderr" type="s13_stderr" layout="none"/>
	<appender name="cat_stderr" type="s13_stderr" layout="catlayout"/>
	<appender name="xml_stderr" type="s13_stderr" layout="xmllayout"/>
        <appender name="user_stderr" type="s13_stderr" layout="userlayout"/>

	<layout name="basic" type="basic"/>
	<layout name="dated" type="dated"/>
	
	<layout name="catlayout" type="s13_cat"/>
	<layout name="xmllayout" type="s13_xml"/>
        <layout name="none" type="s13_none"/>
	<layout name="userlayout" type="s13_userloc"/>
	
	<category name="six13log.log.app.application2" priority="debug" appender="cat_stderr" />
	<category name="six13log.log.app.application3" priority="debug" appender="user_stderr" />
        <category name="six13log.log.app" priority="debug" appender="myrollingfileappender" />

</log4c>


  • cmake生成VS工程(这里方便没放build,一般都是创建build目录放里面)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

二、log4c配置笔记

1)与log4cpp\log4cxx的比较

①Log4cpp & Log4CPlus:C++的日志库,可移植移性相对差些;Log4cxx需要依赖于APR
②Log4c:C的日志库,基本上都是一些纯c的东西,移植性较好

2)log4c的三个基本概念简单介绍(Category, Appender, Layout)

  • 概念说明
    ①Category:用于区分不同的日志,在一个程序中我们可以通过Category来指定很多的日志。
    ②Appdender:用于描述输出流,通过为Category来指定一个Appdender,可以决定将log信息来输出到什么地方去,比如stdout, stderr, rollingfile等等。(rollingpolicy用于描述文件输出的配置策略。)
    ③Layout:用于指定日志信息的格式,通过为Appender来指定一个Layout,可以决定log信息以何种格式来输出,比如是否有带有时间戳, 是否包含文件位置信息等,以及他们在一条log信息中的输出格式的等。
  • 组合关系
    Category, Appender, Layout三者之间的关系,一个Category需要为其指定一个appender, 一个appender亦要为其指定一个layout。

3)配置文件示例

<!DOCTYPE log4c SYSTEM "">
<log4c version="1.2.0">
  <config>
    <bufsize>0</bufsize>
    <debug level="0"/>
    <nocleanup>0</nocleanup>
  </config>
  
  <layout name="dated" type="dated_l"/>
  
  <!-- appenders ===================================== -->
    <appender name="LoadBusinessLog" type="rollingfile" logdir="../etc/log"
       prefix="LoadBusiness-" layout="dated_l" rollingpolicy="Policy1" />
 
    <appender name="CataRollingFileAppender" type="rollingfile" logdir="../etc/log/"
       prefix="testLog" layout="dated" rollingpolicy="RollingPolicy" />
      //输出流名字CataRollingFileAppender,输出流类型rollingfile,输出日志地址../etc/log
      //输出日志格式名字是dated,输出日志文件配置策略名称RollingPolicy

    <!-- category ========================================= -->
    <category name="root" priority="notice"/>   
    // 日志名字叫root,优先级是notice
    
    <category name="framework" priority="info" appender="FrameLog" />  
    // 日志名字叫framework,优先级是info,appender输出流类型名称选择FrameLog
    
    <category name="test.log" priority="trace" appender="CataRollingFileAppender" />
    //日志名字叫test.log,优先级是trace,appender输出流类型名称选择CataRollingFileAppender
    
    <!-- rollingpolicy ======================================= -->
    <rollingpolicy name="Policy1" type="timewin" timetype="1" maxnum="10" />
    //日志文件输出的配置策略名称为Policy1,日志文件输出的配置策略的类型为timewin
    //maxsize:输出日志文件的最大值。默认值为20KB;
    //maxnum:保存的历史日志文件总数。默认值为5
    
    <rollingpolicy name="RollingPolicy" type="sizewin" maxsize="102400" maxnum="10" />
</log4c>

三、log4c概念详细介绍

1)category

①name:日志的名称
②priority:日志的优先级,共有fatal、alert、crit、error、warn、notice、info、debug、trace、notset和unknown11个级别,其级别逐步递增,记录在日志中的数据为小于等于指定级别的数据。
③appender:输出流类型名称,为appender节点的name属性的值。

2)appender

①name:输出流名称
②type:输出流类型,共有stream、syslog、rollingfile三大类
③layout:输出日志的格式的名称,为layout节点的name属性的值。
④rollingpolicy:输出日志文件配置策略名称,为rollingpolicy节点的name属性的值。
⑤rollingpolicy的timewin类型的日志输出为自定义类型

3)layout

①name:输出日志的格式名称
②type:输出日志格式的类型,共有base 、dated、dated_l等格式类型,对于自定义类型也有配置在这里,否则不能够加载。
③base:%P %c - %m/n
     “%P” 日志信息的优先级
     “%c” 日志的名称
     “%m” 日志信息内容
④dated:%d %P %c - %m/n --包含时间
     “%d” 日志信息产生的时间,UTC格式yyyymmdd hh:mm:ss.mis
     “%P” 日志信息的优先级
     “%c” 日志的名称
     “%m” 日志信息内容
⑤dated_l:%d %P %c - %m/n (源代码里面没有,自己增加的)
     “%d” 日志信息产生的时间,本地时间格式yyyymmdd hh:mm:ss
     “%P” 日志信息的优先级
     “%c” 日志的名称
     "%m"日志信息内容

4)rollingpolicy

①name:日志文件输出的配置策略名称。
②type:日志文件输出的配置策略的类型,有sizewin一种类型。
③maxsize:输出日志文件的最大值。默认值为20KB
④maxnum:保存的历史日志文件总数。默认值为5

5)配置文件的路径 :

①${ LOG4C_RCPATH }/log4crc  //环境变量中设置的配置文件夹下log4crc
②${HOME}/.log4crc       //HOME文件夹下log4crc
③/log4crc          //当前可执行文件夹下log4crc

6)环境变量

1)LOG4C_RCPATH:
 holds the path to the main log4crc configuration file 
 #环境变量若未设置,则在工作目录(一般为运行目录)搜索log4crc配置文件. 如果设置了此变量,则所以用log4c库的程序都会使用此路径下的log4c配置文件(可根据category区分).

2)LOG4C_PRIORITY
 holds the "root" category priority 
 #改变root的priority,,

3)LOG4C_APPENDER
 holds the "root" category appender 
 #改变root的appender,,因为root默认没设置appender.

四、log4c代码使用案例及简答封装实例

1)引用头文件注意点

  • 直接引用log4c.h程序编译出错,因此只引用需要的头文件
extern "C" {
#include <log4c/init.h>
#include <log4c/category.h>
}

2)原生实例代码

//.cpp文件

//初始化
int main()
{
	log4c_init();
	//获取一个已有的category
	log4c_category_t* mycat = log4c_category_get("cata.log ");
	//用该category进行日志输出,优先级为DEBUG,输出信息为 "Hello World!"
	log4c_category_log(mycat, LOG4C_PRIORITY_DEBUG, "Hello World!");
	//析构
	log4c_fini();
}

//////备注//////
//在日志输出过程中可以进行格式化输出:
log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "Error code = %d", 12345);
//对于格式化输出也可以有如下写法:
void CLog::Trace(const char * format, ... )
{
   if (log4c_category_is_priority_enabled(mycat, LOG4C_PRIORITY_TRACE))
   {
    a_list argptr;
    va_start(argptr, format);

    log4c_category_vlog(mycat, LOG4C_PRIORITY_TRACE, format, argptr);

    va_end(argptr);
   }
}

3)类C简单封装

(1)log.h
#ifndef _LOG_H_
#define _LOG_H_
 
#include <string.h>
#include <stdlib.h>
 
#ifdef __cplusplus
extern "C"
{
#endif
 
#include "log4c.h"
 
#ifdef __cplusplus
}
#endif
 
#define LOG_PRI_ERROR 		LOG4C_PRIORITY_ERROR
#define LOG_PRI_WARN 		LOG4C_PRIORITY_WARN
#define LOG_PRI_NOTICE 		LOG4C_PRIORITY_NOTICE
#define LOG_PRI_DEBUG 		LOG4C_PRIORITY_DEBUG
#define LOG_PRI_TRACE 		LOG4C_PRIORITY_TRACE
 
 //log_open("category_name"); //category_name一定得是log4crc里面已经定义的category.
extern int log_open(const char *category);
extern void log_message(int priority ,const char* fmt, ...);
extern void log_trace(const char *file , int line , const char *func, const char *fmt ,...);
extern int log_close();
 
#define LOG_ERROR(fmt , args...)	\
	log_message(LOG_PRI_ERROR, fmt, ##args)
#define LOG_WARN(fmt, args...)		\
	log_message(LOG_PRI_WARN, fmt , ##args)
#define LOG_NOTICE(fmt , args...)	\
	log_message(LOG_PRI_NOTICE, fmt , ##args)
#define LOG_DEBUG(fmt , args...)	\
	log_message(LOG_PRI_DEBUG, fmt , ##args)
#define LOG_TRACE(fmt,args...) 		\
	log_trace(__FILE__ , __LINE__ , __FUNCTION__ , fmt ,## args)
 
 
#endif
(2)log.c
#include <log4c.h>
#include <assert.h>
#include "log.h"
 
 
static log4c_category_t *log_category = NULL;
 
 //log_open("category_name"); //category_name一定得是log4crc里面已经定义的category.
int log_open(const char *category)
{
    if (log4c_init() == 1)
    {
        return -1;
    }
    log_category = log4c_category_get(category);
    return 0 ;
}
 
void log_message(int priority , const char *fmt , ...)
{
	va_list ap;
	
	assert(log_category != NULL);
 
	va_start(ap, fmt);
	log4c_category_vlog(log_category , priority , fmt , ap);
	va_end(ap);
}
 
void log_trace(const char *file, int line, const char *fun, 
			const char *fmt , ...)
{
	char new_fmt[2048];
	const char *head_fmt = "[file:%s, line:%d, function:%s]"; 
	va_list ap;
	int n;
	
	assert(log_category != NULL);
	n = sprintf(new_fmt, head_fmt , file , line , fun);
	strcat(new_fmt + n , fmt);
 
	va_start(ap , fmt);
	log4c_category_vlog(log_category , LOG4C_PRIORITY_TRACE, new_fmt , ap);
	va_end(ap);
}
 
 
int log_close()
{
    return (log4c_fini());
}
(3)测试代码test-log.c
#include <stdio.h>
#include "log.h"
 
int main(void)
{
	log_open("<span style="color: rgb(51, 51, 51); line-height: 20px;">mycat</span>");
	LOG_TRACE("trace");
	LOG_ERROR("error");
	LOG_WARN("warn");
	LOG_NOTICE("notice");
	LOG_DEBUG("hello log4c!");
	log_close();
	return 0;
}
(4)配置文件(默认名为log4crc.xml)
  • 备注
    配置文件的搜索是由LOG4C_RCPATH环境变量决定。搜索的配置文件名为log4crc
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE log4c SYSTEM "">
 
<log4c version="1.2.1">
 
        <config>
                <bufsize>0</bufsize>
                <debug level="2"/>
                <nocleanup>0</nocleanup>
				<reread>1</reread>
        </config>
 
        <!-- root category ========================================= -->
        <category name="root" priority="notice"/>
		<category name="mycat" priority="debug" appender="stdout"/>
 
        <!-- default appenders ===================================== -->
        <appender name="stdout" type="stream" layout="basic"/>
        <appender name="stderr" type="stream" layout="dated"/>
        <appender name="syslog" type="syslog" layout="basic"/>
 
        <!-- default layouts ======================================= -->
        <layout name="basic" type="basic"/>
        <layout name="dated" type="dated"/>
		
</log4c>
(5)运行效果
./test-log

[stdout] TRACE    mycat - [file:test-log.c, line:7, function:main]trace
[stdout] ERROR    mycat - error
[stdout] WARN     mycat - warn
[stdout] NOTICE   mycat - notice
[stdout] DEBUG    mycat - hello log4c!

4)类C++单例封装

(1)log.h
#ifndef LOG_H
#define LOG_H
 
#include <log4c/init.h>
#include <log4c/category.h>
 
class MyLog
{
    public:
        void init(const char * str);
        static MyLog * get_instance();
 
        log4c_category_t * mycat;
    private:
        MyLog();
 
        ~MyLog();
 
    private:
        static MyLog * _instance;
 
};
 
#define LOG_DEBUG(msg, args...) \
{ \
    const log4c_location_info_t locinfo = LOG4C_LOCATION_INFO_INITIALIZER(NULL); \
    log4c_category_log_locinfo(MyLog::get_instance()->mycat, &locinfo, LOG4C_PRIORITY_DEBUG, msg, ##args); \
}
 
#define LOG_ERROR(msg, args...) \
{ \
    const log4c_location_info_t locinfo = LOG4C_LOCATION_INFO_INITIALIZER(NULL); \
    log4c_category_log_locinfo(MyLog::get_instance()->mycat, &locinfo, LOG4C_PRIORITY_ERROR, msg, ##args); \
}
 
#define LOG_TRACE(msg, args...) \
{ \
    const log4c_location_info_t locinfo = LOG4C_LOCATION_INFO_INITIALIZER(NULL); \
    log4c_category_log_locinfo(MyLog::get_instance()->mycat, &locinfo, LOG4C_PRIORITY_TRACE, msg, ##args); \
}
 
#endif
(2)log.cpp
#include <stdio.h>
#include "log.h"
 
 
MyLog * MyLog::_instance = NULL;
 
MyLog::MyLog()
{
 
}
 
MyLog::~MyLog()
{
    if (log4c_fini() != 0)
        printf("log4c fini error!\n");
}
 
void MyLog::init(const char * str)
{
    if (log4c_init() != 0) {
        printf("log4c init error!\n");
        return;
    }
 
    mycat = log4c_category_get(str);
}
 
MyLog * MyLog::get_instance()
{
    if (_instance == NULL) {
        _instance = new MyLog;
    } else {
 
    }
 
    return _instance;
}
(3)main.cpp
#include "classA.h"
#include "classB.h"
 
//#include <log4c/init.h>
//#include <log4c/category.h>
#include "log.h"
 
int main(int argc,char** argv)
{
 
   MyLog::get_instance()->init("zhenglq");
 
    ClassA ca;
    ClassB cb;
 
    ca.printStr();
    cb.printStr();
 
    /* log4c init */
//    log4c_init();
 
    /* get category */
//    log4c_category_t* mycat = log4c_category_get("aiwujie");
 
    /* out log */
//    log4c_category_log(mycat, LOG4C_PRIORITY_DEBUG,"Hello World!");
 
//    log4c_fini();
 
   LOG_DEBUG("hello log4c!");
 
 
 
 
 
    return 0;
}
(4)配置文件log4crc
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE log4c SYSTEM "">
<log4c>
        <config>
                <bufsize>0</bufsize>
                <debug level="0"/>
                <nocleanup>0</nocleanup>
        </config>
 
        <category name="root" priority="notice"/>
 
        <appender name="log4.log" type="stream" layout="dated"  logdir="." prefix="testLog"/>
 
        <layout name="dated" type="dated"/>
 
        <category name="aiwujie" priority="debug" appender="log4.log"/>
</log4c>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值