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;
}

  

简单的跨平台c/c++日志记录的更多相关文章

  1. Ibatis.net 1.6.2 简单配置及Log4.Net日志记录

    看似简单的Ibatis配置起来注意的地方还挺多.里面的设置及功能还算强大.昨晚配置了半宿,结果一运行还是各种错误.急的直冒汗.果断下载实例去研究.英文不好文档只能作为功能参考. 下面一步步进入Ibat ...

  2. 【转】使用Log4Net进行日志记录

    首先说说为什么要进行日志记录.在一个完整的程序系统里面,日志系统是一个非常重要的功能组成部分.它可以记录下系统所产生的所有行为,并按照某种规范表达出来.我们可以使用日志系统所记录的信息为系统进行排错, ...

  3. php 简单通用的日志记录方法

    使用file_put_contents 方法来实现简单便捷的日志记录功能 方法1: // use \r\n for new line on windows, just \n on linux func ...

  4. 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存

    代码已上传Github+Gitee,文末有地址 上回<从壹开始前后端分离[ .NET Core2.0 Api + Vue 2.0 + AOP + 分布式]框架之九 || 依赖注入IoC学习 + ...

  5. Net Core平台灵活简单的日志记录框架NLog+SqlServer初体验

    Net Core平台灵活简单的日志记录框架NLog+SqlServer初体验 前几天分享的"[Net Core平台灵活简单的日志记录框架NLog+Mysql组合初体验][http://www ...

  6. Net Core平台灵活简单的日志记录框架NLog+Mysql组合初体验

    Net Core平台灵活简单的日志记录框架NLog初体验 前几天分享的"[Net Core集成Exceptionless分布式日志功能以及全局异常过滤][https://www.cnblog ...

  7. Z从壹开始前后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存

    本文梯子 本文3.0版本文章 代码已上传Github+Gitee,文末有地址 大神反馈: 零.今天完成的深红色部分 一.AOP 之 实现日志记录(服务层) 1.定义服务接口与实现类 2.在API层中添 ...

  8. 简单的C#日志记录和弹出提示

    记录这个博客的想法只有两点, 一,在使用webserver的时候如果你不好调用本地server端,那么你可以启用日志来查看异常.当然也可以调用本地的server端.这里简单说一下.不是本文的重点. 发 ...

  9. C++实现简单的日志记录

    C++实现简单的日志记录 //dlogger.h #ifndef DLOGGER_H #define DLOGGER_H #include <iostream> #include < ...

随机推荐

  1. 黑马程序员_Java基础:集合总结

    ------- android培训.java培训.期待与您交流! ---------- 一.集合概念 相信大家都知道,java是一门面向对象的编程语言,而对事物的体现都是以对象的形式,所以为了方便对多 ...

  2. H3C qos 简单配置

    qos 有三种服务模型 Best-Effort service(尽力而为服务模型) Integrated service(综合服务模型,简称Int-Serv) Differentiated servi ...

  3. Extjs的学习及MIS系统实践应用(系列文章)

    本系列文章从Extjs的实际运用出发,结合系统开发的实践经验,详细解释Extjs的基本控件及控件扩展的用法,和在平时的学习运用中一步一步查阅的资料.积累经验的集锦.标题及链接奉上,用一个小程序,开启了 ...

  4. WP7推送通知服务

    原文地址http://www.cnblogs.com/Joetao/articles/2214482.html (一)为什么使用推送通知服务(1)Windows Phone执行模型决定只有一个第三方的 ...

  5. linux redmine 搭建

    redmine搭建过程参考:http://www.tuicool.com/articles/InMbym 注意事项: 配置文件必须以2个空格开始 启动(指定了端口,和绑定的IP): ruby bin/ ...

  6. unity 实现简单的分离

    在网上随便搜一搜资料就可以找到很多关于Mvc ,MVVM,StrangeIoc等有关显示与数据分离的博客,很多大神也是讲的蛮有道理的,但是这些框架理解起来有一定的难度, 这时候肯定有人说有现成的框架为 ...

  7. savepoint原理

    保存点 在MySQL中, 保存点SAVEPOINT属于事务控制处理部分.利用SAVEPOINT可以回滚指定部分事务,从而使事务处理更加灵活和精细.SAVEPOINT相关的SQL语句如下 SAVEPOI ...

  8. 分享我的“艺术品”:公共建筑能耗监测平台的GPRS通讯服务器的开发方法分享

    在这个文章里面我将用一个实际的案例来分享如何来构建一个能够接受3000+个连接的GPRS通讯服务器软件,这个软件被我认为是一个艺术品,实现周期为1.5个月,文章很长,有兴趣的同志慢慢看.在这里,我将分 ...

  9. 可在广域网部署运行的QQ高仿版 -- GG叽叽V2.0,增加网盘和远程磁盘功能(源码)

    尽力2~3周发布一个版本,我这次也没有失言.这段时间内,我仿照QQ的微云功能,在GG中增加了网盘的功能,而且,我还自创了一个QQ没有的新的功能:远程磁盘.正如远程桌面一样,远程磁盘允许我们像访问本地磁 ...

  10. C#函数式编程

    提起函数式编程,大家一定想到的是语法高度灵活和动态的LISP,Haskell这样古老的函数式语言,往近了说ruby,javascript,F#也是函数式编程的流行语言.然而自从.net支持了lambd ...