跨平台c/c++日志记录 CLog (支持多线程)
CLog.h
#include <stdlib.h> #pragma once #ifndef _CLOG #define _CLOG #define CLOG_DEBUG 0 #define CLOG_INFO 1 #define CLOG_WARNING 2 #define CLOG_ERROR 3 #define stderr_message(exp, message) { fprintf(stderr,"-------------ERROR-----------------\n"); fprintf(stderr,"Failed:%s\nMessage:%s\nLine:%d\nFile:%s\n",#exp,message,__LINE__,__FILE__);fprintf(stderr,"-------------ERROR-----------------\n"); /*exit(EXIT_FAILURE);*/} //Clog(int level, char *msg) #define CLog(level,msg){_CLog(level,msg,__LINE__,__FILE__);} //CLogDebug(char *msg) #define CLogDebug(msg){CLog(CLOG_DEBUG,msg);} //CLogError(char *msg) #define CLogError(msg){CLog(CLOG_ERROR,msg);} //CLogInfo(char *msg) #define CLogInfo(msg){CLog(CLOG_INFO,msg);} //CLogWarning(char *msg) #define CLogWarning(msg){CLog(CLOG_WARNING,msg);} #endif #ifdef __cplusplus extern "C" { #endif //init clog ! log_path is logfile path! void InitCLog(char *log_path); //this fun is logging! void _CLog(int level, char *msg,int line,char *file); //freee clog! void FreeeClog(); #ifdef __cplusplus } #endif
CLog.c
#include "CLog.h" #include <stdio.h> #include <stdarg.h> #include <time.h> #ifdef WIN32 #include <windows.h> #else #include <pthread.h> #endif #ifndef _CLOGSTATIC #define _CLOGSTATIC const char CLOGLevelName[4][8] = { "debug", "info", "warning", "error" }; FILE *fp = NULL; char now_file_name[11]; char *log_path; #ifdef WIN32 CRITICAL_SECTION g_cs; #else pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; #endif #endif void now_date_str(char *date_str) { time_t nowtime; struct tm *timeinfo; time(&nowtime); timeinfo = localtime(&nowtime); sprintf(date_str, "%d_%d_%d", timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday); } void now_datetime_str(char *datetime_str) { time_t nowtime; struct tm *timeinfo; time(&nowtime); timeinfo = localtime(&nowtime); sprintf(datetime_str, "%d_%d_%d %d:%d:%d", timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec ); } void lock() { #ifdef WIN32 EnterCriticalSection(&g_cs); #else pthread_mutex_lock(&mutex1); #endif } void unlock() { #ifdef WIN32 LeaveCriticalSection(&g_cs); #else pthread_mutex_unlock(&mutex1); #endif } long thread_id() { #ifdef WIN32 return GetCurrentThreadId(); #else return pthread_self(); #endif } void open_log_file() { char *filename = (char*)malloc(strlen(log_path) + strlen(now_file_name) + 1); sprintf(filename, "%s/%s.%s", log_path, now_file_name, "txt"); fp = fopen(filename, "ab+"); if (fp == NULL) { stderr_message(fp == NULL, "(clog) fopen error !"); return; } } //mk dirs void mkdir_p(char *dir) { //copy char * dir_c = (char*)malloc(strlen(dir) + 1); memcpy(dir_c, dir, strlen(dir) + 1); dir = dir_c; char * temppath = (char*)malloc(strlen(dir) + 1); int tempindex = 0; while (*dir_c != ‘\0‘) { if (*dir_c == ‘\\‘) *dir_c = ‘/‘; if (*dir_c == ‘/‘) { tempindex = dir_c - dir; memcpy(temppath, dir, tempindex); temppath[tempindex] = ‘\0‘; if (_access(temppath, 0) != 0) _mkdir(temppath); } dir_c++; } if (_access(dir, 0) != 0) _mkdir(dir); free(dir); free(temppath); } void InitCLog(char *path) { #ifdef WIN32 InitializeCriticalSection(&g_cs); #endif if (path == NULL) stderr_message(path == NULL, "(clog) logpath is null !"); now_date_str(now_file_name); int pathlength = strlen(path); log_path = (char*)malloc(pathlength*sizeof(char) + 1); strcpy(log_path, path); if (log_path[pathlength - 1] == ‘/‘) log_path[pathlength - 1] = ‘\0‘; mkdir_p(log_path); open_log_file(); } void _CLog(int level, char *msg, int line, char *file) { lock(); if (level<0 || level>3) { stderr_message(level<0 || level>3, "(clog) level overflow!"); return; } if (fp == NULL) { stderr_message(fp == NULL, "(clog) clog not init!"); return; } char temp_now_file_name[11]; now_date_str(temp_now_file_name); if (strcmp(temp_now_file_name, now_file_name) != 0) { strcpy(now_file_name, temp_now_file_name); fclose(fp); open_log_file(); if (fp == NULL) { stderr_message(fp == NULL, "(clog) clog init error!"); return; } } char* info = (char*)malloc(strlen(msg) + 80 + strlen(file)); char datetimestr[21]; now_datetime_str(datetimestr); sprintf(info, "%s thread:%d %s \r\n%s\r\nfile:%s line:%d\r\n", datetimestr, thread_id(), CLOGLevelName[level], msg, file, line); fwrite(info, strlen(info), 1, fp); fflush(fp); free(info); unlock(); } void FreeeClog() { lock(); if (fp != NULL) fclose(fp); free(log_path); unlock(); }
Example:
#include "stdafx.h"//Without this header file under linux #include "CLog.h" #include <stdlib.h> #ifdef WIN32 #include <Windows.h> #include <process.h> #else #include <pthread.h> #endif #define thread_num 10 void thread_fun() { int i = 0; for (; i < 1000; i++) { CLog(CLOG_DEBUG, "this debug message!"); CLog(CLOG_INFO, "this info!╮(╯▽╰)╭"); CLog(CLOG_WARNING, "警告!this warning!!"); CLog(CLOG_ERROR, "Error!!"); } } #ifdef WIN32 unsigned _stdcall ThreadProc(void* param) { thread_fun(); return 0; } void win32_thread_test() { HANDLE handle[thread_num]; int i = 0; for (; i < thread_num; i++) { handle[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, NULL, NULL); } for (i = 0; i < thread_num; i++) { WaitForSingleObject(handle[i], INFINITE); CloseHandle(handle[i]); } } #else void *linux_threadfun(void *arg) { thread_fun(); } void linux_thread_test() { pthread_t pthreadarray[thread_num]; int i = 0; for (; i < thread_num; i++) { pthreadarray[i] = pthread_create(&pthreadarray[i], NULL, linux_threadfun, NULL); } for (i = 0; i < thread_num; i++) { pthread_join(&pthreadarray[i], NULL); } } #endif int main() { /*Example: InitCLog ("D:/ntg/logs"); disk directory InitCLog ("logs"); the current directory under the logs directory InitCLog ("test/log/codelog"); the current directory est/log/codelog directory */ InitCLog("D:/Logs"); //Loging Example: CLog(CLOG_DEBUG, "this debug message!"); CLog(CLOG_INFO, "this info!╮(╯▽╰)╭"); CLog(CLOG_WARNING, "this warning! ( ⊙ o ⊙ )啊!"); CLog(CLOG_ERROR, "Error!!"); //or CLogInfo("这是info!"); CLogError("报错!"); CLogDebug("debug!!"); CLogWarning("指针为null!"); //Multithreaded Test Start #ifdef WIN32 win32_thread_test(); #else linux_thread_test(); #endif //Multithreaded Test End //The program exits when the need to call FreeeClog free FreeeClog(); system("pause"); return 0; }
文章来自:http://www.cnblogs.com/dark89757/p/4792841.html