我弄了好久了 就是在网上把cximage 下下来后 就配置 :
1。先编译所有的。dsw
2.将所有的。dsp 添加到我的工程workspace下
3.在工程里面dependces 打勾 在工程的setting中 将c/c++ code genaeration use run-time library multithreaded DLL
Precomplied Headers 选NOT using precomplied headers 然后在 Additional include directories 下添加什么啊? 是哪个文件的路径?
4.在刚才里添加 #include “cximage.h”
编译出错 有31个错误 说是找不到路径
纠结死我了 教我啊!!!
1。先编译所有的。dsw
2.将所有的。dsp 添加到我的工程workspace下
3.在工程里面dependces 打勾 在工程的setting中 将c/c++ code genaeration use run-time library multithreaded DLL
Precomplied Headers 选NOT using precomplied headers 然后在 Additional include directories 下添加什么啊? 是哪个文件的路径?
4.在刚才里添加 #include “cximage.h”
编译出错 有31个错误 说是找不到路径
纠结死我了 教我啊!!!
解决方案 »
- 像WIN7那样的玻璃背景如何实现的?
- CString 字符替换的简单问题?
- 问个数据转换的问题
- classwizard中看不见基于CObject的类
- CSDN的论坛是谁做的?为何如此丑陋?
- 想让程序在某处暂停一段时间该怎么办
- 看了VC技术内幕中的COM部分,不是太明白,求一些COM的资料?另再问MFC中关加解密,信息摘要,数字签名的几个类?谢谢,在线等。
- 如何解决VC和Java通过socket通信时遇到的字符集问题
- 能否在VC的DLL中实现多线程,在Delphi中使用?
- 如何在HTMLVIEW的浏览器中禁止文件下载?已经禁止了右键,可是如果点左键还是会提示的
- 关于vc中添加新类文件的问题
- VC树形控件问题求助
Log4j据说是最闻名的日志文件类库,有针对于C++或者.NET的移植版本。一直不明白日志文件有什么特殊之处,也没有研究其功能强大在何处。理想中的日志文件类库功能应该具备:一个中心、两项基本功能、三个补充要求!
一个中心点: 使用简单
就是使用的时候可以感觉日志功能是随插随用,不用在代码层次上做太多前期的步骤。
两个基本功能:日志类型管理、日志文件管理
日志类型管理包括:格式化输出、日期时间标记等。前者可以考虑为日志分类,后者带上时间标记便于跟踪调试分析。
日志文件管理包括:日志文件的大小约定、按时间段整理等
三点补充要求:多种类型信息输出、多个进程输出到同一个日志文件、多进程线程同时输出时互斥操作
以下是根据在实际过程中的运用,封装一个简单的日志文件功能模块。麻雀虽小,但是却满足以上所有要求。其中,对于日志文件管理这块简单点约定输出到指定文件名。由于采用CString,因此仅适用于MFC!但是可以方便的改造为纯C|C++。//===============================================================// LOG::简单的日志工具// 日志功能包应该包括以下两块功能:// 1. 每个日志文本串// 目前日志文本串包括 [prefix][datetime][type][info...]// a.多个进程输出到同一个日志文件,可通过prefix来区分每个进程; 可以忽略// b.datetime可以用来测试时间// c.类型可以设定[error|warn|debug],// 由使用者任意使用,并不做明确标记; 也可以忽略// d.info,可以根据实际情况任意格式化输出,类似printf// 2. 日志文件// a. 可将日志串保存到文本,或者自己处理// b. 支持并发写操作// c. 日志文件的管理//=============================================================== --------------------------------------------------------------------------------.h文件
class LOG{public:LOG();virtual ~LOG(); public://-日志文件-//----如果没有指定,则为exe所在路径下的log.log文件----static CString GetLogFile();static short SetLogFile(LPCTSTR strPath);static short ViewLogFile(); //-前缀-//----如果多个进程往同一个文件输出日志,可以为每个进程设置一个前缀----//----前缀出现在日期时间之前----static short SetPrefix(LPCTSTR strPrefix); //-日志信息-//-获取日志字符串,可以另外-static CString sOutV(LPCTSTR strType, LPCTSTR strFormat = NULL, va_list valist = NULL);static CString sOut0(LPCTSTR strType, LPCTSTR strFormat = NULL,...);static CString sOut ( LPCTSTR strFormat = NULL,...); //-将日志信息输出到文件-static short OutV(LPCTSTR strType, LPCTSTR strFormat = NULL, va_list valist = NULL);static short Out0(LPCTSTR strType, LPCTSTR strFormat = NULL,...);static short Out (LPCTSTR strFormat = NULL,...); protected:static CString s_strLogFile;static CString s_strLogPrefix;static HANDLE s_hWriteEvent;}; --------------------------------------------------------------------------------.cpp文件
// 得到可执行程序所在目录// BOOL bIncludeSep -- 是否包含最后的分隔符"\"CString GetExePath(BOOL bIncludeSep){// 得到当前的文件名CString strFileName;GetModuleFileName(AfxGetInstanceHandle(),strFileName.GetBuffer(_MAX_PATH),_MAX_PATH);strFileName.ReleaseBuffer();// 得到当前目录strFileName=strFileName.Left(strFileName.ReverseFind(_T('\\'))+1); if(bIncludeSep)return strFileName;elsereturn strFileName.Left(strFileName.GetLength()-1);} //-获取最后的文件名 如果给定文件不是全路径,就是相对于exe-CString GetFileForExePath(LPCTSTR strCurFileName){CString strPath = strCurFileName;if(!strPath.IsEmpty()){//-相对路径-if(strPath.Find(_T(":"))<=0) { strPath.Format(_T("%s%s"), GetExePath(FALSE), strCurFileName); } } return strPath; } #define LOG_EVENT _T("ChyLogWrite") CString LOG::s_strLogFile = _T(""); CString LOG::s_strLogPrefix = _T(""); HANDLE LOG::s_hWriteEvent = NULL; LOG::LOG() {} LOG::~LOG() {} short LOG::SetLogFile(LPCTSTR strPath){if(strPath==NULL || strPath[0]==0)s_strLogFile = GetFileForExePath("log.log");elses_strLogFile = GetFileForExePath(strPath); return 1;} CString LOG::GetLogFile(){return s_strLogFile;} short LOG::ViewLogFile(){CString strLogFile = GetLogFile();ShellExecute(NULL, _T("open"), strLogFile, NULL, NULL, SW_SHOW);return strLogFile.IsEmpty()?0:1;} short LOG::SetPrefix(LPCTSTR strPrefix){if(strPrefix && strPrefix[0]){s_strLogPrefix = strPrefix;} return 1;} CString LOG::sOutV(LPCTSTR strType, LPCTSTR strFormat, va_list valist){ CString strPart_Prefix;if(!s_strLogPrefix.IsEmpty()){strPart_Prefix.Format(_T("[%s]"), s_strLogPrefix);} CString strPart_Time;{SYSTEMTIME sysTime = {0};GetLocalTime(&sysTime);strPart_Time.Format(_T("[%2d-%2d %2d:%2d:%2d_%3d]"), sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds); } CString strPart_Type;if(strType && strType[0]){strPart_Type.Format(_T("[%s]"), strType);} CString strPart_Info;{ strPart_Info.FormatV(strFormat, valist);} CString str = strPart_Prefix + strPart_Time + strPart_Type+ strPart_Info; return str;} CString LOG::sOut0(LPCTSTR strType, LPCTSTR strFormat,...){va_list valist;va_start(valist, strFormat); CString strInfo = sOutV(strType, strFormat, valist);va_end(valist); return strInfo;} CString LOG::sOut(LPCTSTR strFormat,...){va_list valist;va_start(valist, strFormat);CString strInfo = sOutV(NULL, strFormat, valist);va_end(valist); return strInfo;} short LOG::OutV(LPCTSTR strType, LPCTSTR strFormat, va_list valist){//--if(s_hWriteEvent==NULL){s_hWriteEvent = OpenEvent(0, FALSE,LOG_EVENT);if(s_hWriteEvent==NULL)s_hWriteEvent = CreateEvent(NULL, FALSE, TRUE, LOG_EVENT); } WaitForSingleObject(s_hWriteEvent, INFINITE); //-打开关闭文件-if(s_strLogFile.IsEmpty())SetLogFile(NULL);CStdioFile file;if(file.Open(s_strLogFile, CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite)){CString strPart_NewLine = _T("\n");CString strInfo = sOutV(strType, strFormat, valist); CString str = strPart_NewLine + strInfo; file.SeekToEnd();file.WriteString(str);file.Close();} SetEvent(s_hWriteEvent); return 1;} short LOG::Out0(LPCTSTR strType, LPCTSTR strFormat,...){va_list valist;va_start(valist, strFormat); short rtn = OutV(strType, strFormat, valist);va_end(valist); return rtn;} short LOG::Out(LPCTSTR strFormat,...){va_list valist;va_start(valist, strFormat);short rtn = OutV(NULL, strFormat, valist);va_end(valist); return rtn;} --------------------------------------------------------------------------------使用说明
//-设定日志文件,建议在Exe初始化时设定-//-设置相对路径则表示exe所在路径下-//-如果不设定则为exe所在路径下的log.log文件-LOG::SetLogFile("bbb.log"); //-获取日志文本串,可以自行处理,例如输出到界面-CString str;str = LOG::sOut0("debug", "hello");str = LOG::sOut0("warn5", "hello %d", 25);str = LOG::sOut0("warn3", "hello %s, you have %d apples!", "libai", 10);str = LOG::sOut ("hello %s, you have %d apples!", "libai", 10); //-输出到文件-LOG::Out0("debug", "hello");LOG::Out0("warn5", "hello %d", 25);LOG::Out0("warn3", "hello %s, you have %d apples!", "libai", 10);LOG::Out ("hello %s, you have %d apples!", "libai", 10); //-查看日志文件-LOG::ViewLogFile();
/*Windows Mobile下使用Native C++开发日志类
背景
这段业余时间一直都在开发iToday。在iToday中加入日志管理。关于iToday,可以参考那些一些文章。
开源(Open Source)那些事儿 (一)
开源那些事儿 (二) - iToday开源项目计划
开源那些事儿(三)-iToday的总体设计
开源那些事儿(四)-如何使用CodePlex进行项目管理
简介
日志管理是程序不可以缺少的一个重要组成部分,对于长期运行的后台程序尤为重要,尽管经过了大量的测试,
但是在实际运行环境下,程序未免有出错的时候。有时候由于第三方原因导致的,例如电信网络质量下载,掉包等等。
在一些看似莫名其妙的问题下,日志文件很多时候就成了救命绳。bug free是我们一直追求的目标,但是我永远不能保证bug free,
每次我在面试中说这句话,做****出生的人会翻白眼,做技术的人会会心一笑。我能保证的是如何尽快的troubleshooting,
提高质量,日志文件在这过程中又是最重要的手段之一。
下面文章讲述使用Native C++对Windows Embedded CE和Windows Mobile日志文件类的封装代码先上代码,下面分析。
需要iToday全部代码也可以到codeplex上去下载。
类定义文件*/
typedef enum tagLOG_LEVEL
{
LOG_TRACE, //跟踪
LOG_INFO, //报告
LOG_WARNING, //警告
LOG_ERROR, //错误
LOG_FATAL, //严重错误
LOG_NONE = 10,//没错误
}LOG_LEVEL;class Logger
{
public:
static Logger& Instance();
static void SetLogFilePath( const std::string& strFilePath);
static void SetLogLevel( const LOG_LEVEL enLogLevel);
//va_list在win32/vc++6.0下的讨论1. 简介va_list、va_arg、va_end是为了处理变参数的函数而做的宏定义,这些定义会因为平台(cpu、操作系统
)和环境(编译系统)的不同而有所不同。简单原理:编译系统编译时,会将函数的参数依次放到栈中,这样根据固定参数的地址以及固定参数给出的相
关信息很容易得到可变参数的个数、类型、值。注意一点,这些或者是固定参数给出的信息,虽然不是直接给出的
;或者是程序写作者自我约定。得到了可变参数,剩下的处理和普通函数一样了。以下的理解和实例均在win32&vc++6.0环境中的情况。2. 结合一个实例看简单原理实例如下(win2kserver vc++6.0编译通过)://============================//求若干个整数的平均值#include #include int AveInt(int,...); void main(){ printf("%d\t",AveInt(2,2,3)); printf("%d\t",AveInt(4,2,4,6,8)); return;} int AveInt(int num,...){ int ReturnValue=0; int i=num; va_list myvalist; va_start(myvalist,num); while(i>0) { ReturnValue+=va_arg(myvalist,int); i--; } return ReturnValue/=num;}//===============================(1) 分配情况:跟第二次调用AveInt(4,2,4,6,8),看下参数在内存中的分配,见下图。 图1明显,参数依次连续分配;(2) 参数的个数:由第一个参数给定;(3) 参数类型:我约定为整数;(4) 参数值:明显了。3. 两个小知识(自我整理下)(1) win32 vc++编译内存分配由高址向低址进行;参数调用时,参数入栈顺序:从最后一个开始,直到第一个。通过上图可以看到这两点。(2) 内存对齐分为结构成员内存对齐和栈内存对齐。前者要求:字、双字和四字在自然边界上不需要在内存中对齐。
(对字、双字和四字来说,自然边界分别是偶数地址、可以被4整除的地址、和可以被8整除的地址。)
一个字或双字操作数跨越了4字节边界,或者一个四字操作数跨越了8字节边界,被认为未对齐的。后者要求:总保持对齐,而且对齐在4字节边界上。两者区别:前者是可以通过工具控制对齐边界的,如在vc++中就可以通过控制选项控制边界;
而后者是不能控制的,必须对齐的,毕竟栈的效率太影响到程序性能了。4. 宏定义以下是vc++6.0定义在stdarg.h文件中的关于x86平台的部分宏定义:typedef char * va_list;#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )#define va_end(ap) ( ap = (va_list)0 )结合上例,调用AveInt(4,2,4,6,8),当运行了va_start(myvalist,num);
之后,根据定义myvalist =(va_list)&num+_INTSIZEOF(i),这样myvalist指向第一个可变参
数2;第一次运行va_arg(myvalist,int);后,先让myvalist+= _INTSIZEOF(int)指向下一个可变参
数4,然后在取出前面的可变参数2进行处理;依此类推。