就像DCMTK官方论坛说的那个问题一样:问题:自定义Appender输出DCMTK的oflog
DCMTK日志输出类
大家都知道:DCMTK只提供下面四个日志输出类。
FileAppender: Appends log events to a file.(将DCMTK日志输出到一个文件中)
ConsoleAppender:ConsoleAppender appends log events to STD_NAMESPACE cout
or STD_NAMESPACE cerr
using a layout specified by the user.(将DCMTK日志输出到控制台cmd)
log4cplus::NullAppender:Appends log events to ......(不输出,空的)
SocketAppender:Sends spi::InternalLoggingEvent objects to a remote a log server.(将该日志事件发送给远程服务器)
因为我需要在自己的Qt Gui项目中也输出DCMTK日志,供系统测试或者通过我项目的日志模块登记到数据库、文件中。总之我需要把DCMTK的日志模块集成到自己的Gui项目中。于是我自定义了一个GuiAppender类。
GuiAppender:
实现将DCMTK日志事件捕获,并将日志输出在VS2008的Debug窗口中,也可以后期供调用。
实现源码
我的GuiAppender类 源码
#ifndef GUIAPPENDER_H
#define GUIAPPENDER_H
#include "dcmtk/oflog/config.h"
#include "dcmtk/oflog/appender.h"
#include "dcmtk/oflog/helpers/property.h"
#include <sstream>
namespace log4cplus
{
class GuiAppender : public Appender
{
public:
GuiAppender();
GuiAppender(const log4cplus::helpers::Properties& properties, log4cplus::tstring& error);
virtual ~GuiAppender();
// Methods
virtual void close();
protected:
virtual void append(const log4cplus::spi::InternalLoggingEvent& event);
//声明一个ostringsteam对象
STD_NAMESPACE ostringstream outString ;
private:
// Disallow copying of instances of this class
GuiAppender(const GuiAppender&);
GuiAppender& operator=(const GuiAppender&);
};
} // end namespace log4cplus
#endif // GUIAPPENDER_H
#include "GuiAppender.h"
#include <string>
#include <QDebug>
#include <QString>
log4cplus::GuiAppender::GuiAppender()
{
}
log4cplus::GuiAppender::GuiAppender(const log4cplus::helpers::Properties& properties, tstring&)
: Appender(properties)
{
}
log4cplus::GuiAppender::~GuiAppender()
{
}
void
log4cplus::GuiAppender::close()
{
}
// This method does not need to be locked since it is called by
// doAppend() which performs the locking
void
log4cplus::GuiAppender::append(const spi::InternalLoggingEvent& event)
{
//格式化输入DCMTK日志
layout->formatAndAppend(outString, event);
//获取DCMTK日志字符串流
STD_NAMESPACE string m = outString.str();
//将C++标准字符串流,转换成QString
QString t = QString::fromStdString(m);
//输出调试信息
qDebug() << t;
//清空
outString.str("");
}
主程序测试。
/*
*
* Copyright (C) 2011-2012, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*
* OFFIS e.V.
* R&D Division Health
* Escherweg 2
* D-26121 Oldenburg, Germany
*
*
* Module: dcmnet
*
* Author: Michael Onken
*
* Purpose: Test for move feature of the DcmSCU class
*/
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
#include "dcmtk/dcmnet/diutil.h"
#include "DcmTestSCU.h"
#include <QtGui/QApplication>
#include <QDebug>
#include "dcmtk/oflog/oflog.h"
#include "GuiAppender.h"
#define OFFIS_CONSOLE_APPLICATION "testscu"
static OFLogger echoscuLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION);
static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v"
OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $";
// our application entity title used for calling the peer machine
#define APPLICATIONTITLE "TEST-SCU"
// host name of the peer machine "www.dicomserver.co.uk"
#define PEERHOSTNAME "10.3.2.84"
// TCP/IP port to connect to the peer machine "11112"
#define PEERPORT 5104
// application entity title of the peer machine
#define PEERAPPLICATIONTITLE "MOVESCP"
// MOVE destination AE Title
#define MOVEAPPLICATIONTITLE "TEST-SCU"
#define QRResponse FINDResponse
static Uint8 findUncompressedPC(const OFString& sopClass,
DcmSCU& scu)
{
Uint8 pc;
pc = scu.findPresentationContextID(sopClass, UID_LittleEndianExplicitTransferSyntax);
if (pc == 0)
pc = scu.findPresentationContextID(sopClass, UID_BigEndianExplicitTransferSyntax);
if (pc == 0)
pc = scu.findPresentationContextID(sopClass, UID_LittleEndianImplicitTransferSyntax);
return pc;
}
// ********************************************
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
/* Setup DICOM connection parameters */
OFLog::configure(OFLogger::DEBUG_LOG_LEVEL);
OFLOG_DEBUG(echoscuLogger, "OFLOG_DEBUG");
/* specify log pattern */
OFauto_ptr<log4cplus::Layout> layout(new log4cplus::PatternLayout("%D{%Y-%m-%d %H:%M:%S.%q} %5p: %m%n"));
//建立Gui日志输出类
log4cplus::SharedAppenderPtr guiAppender(new log4cplus::GuiAppender());
guiAppender->setLayout(layout);
//获取全局日志对象
log4cplus::Logger log = log4cplus::Logger::getRoot();
//去除所有日志输出类
log.removeAllAppenders();
//加入Gui输出类
log.addAppender(guiAppender);
//设置日志输出层
log.setLogLevel(OFLogger::INFO_LOG_LEVEL);
//测试输出一个error日志
OFLOG_ERROR(log, "There are six log levels and each provides a OFLOG_level() macro");
//继续测试,输出DCMTK C-Echo动作产生的INFO
//后面是DCMTK的DcmNet模块中 网络通信的测试,大家不需要了解
DcmTestSCU scu;
// set AE titles
scu.setAETitle(APPLICATIONTITLE);
scu.setPeerHostName(PEERHOSTNAME);
scu.setPeerPort(PEERPORT);
scu.setPeerAETitle(PEERAPPLICATIONTITLE);
// Use presentation context for FIND/MOVE in study root, propose all uncompressed transfer syntaxes
OFList<OFString> ts;
ts.push_back(UID_LittleEndianExplicitTransferSyntax);
ts.push_back(UID_BigEndianExplicitTransferSyntax);
ts.push_back(UID_LittleEndianImplicitTransferSyntax);
scu.addPresentationContext(UID_FINDStudyRootQueryRetrieveInformationModel, ts);
scu.addPresentationContext(UID_MOVEStudyRootQueryRetrieveInformationModel, ts);
scu.addPresentationContext(UID_VerificationSOPClass, ts);
/* Initialize network */
OFCondition result = scu.initNetwork();
if (result.bad())
{
DCMNET_ERROR("Unable to set up the network: " << result.text());
return 1;
}
/* Negotiate Association */
result = scu.negotiateAssociation();
if (result.bad())
{
DCMNET_ERROR("Unable to negotiate association: " << result.text());
return 1;
}
/* Let's look whether the server is listening:
Assemble and send C-ECHO request
*/
result = scu.sendECHORequest(0);
if (result.bad())
{
DCMNET_ERROR("Could not process C-ECHO with the server: " << result.text());
return 1;
}
scu.closeAssociation(DCMSCU_RELEASE_ASSOCIATION);
return a.exec();
}
实现结果
最终结果,将DCMTK日志输出到VS2008的Debug窗口中。
------------------------------------
柳北风儿
http://qimo601.iteye.com
------------------------------------