由于要使用到log4cpp的库,而log4c的资料是非常的少,也懒得去研究它的用法,于是就决定试试混合编程者玩意。
首先先引用下C++它的father: Stroustrup的一篇文章《C++ Style and Technique FAQ》(~bs/bs_faq2.html)里的一小个片段:
Just declare the C function ``extern "C"'' (in your C++ code) and call it (from your C or C++ code). For example:
// C++ code
extern "C" void f(int); // one way
extern "C" { // another way
int g(double);
double h();
};
void code(int i, double d)
{
f(i);
int ii = g(d);
double dd = h();
// ...
}
The definitions of the functions may look like this:
/* C code: */
void f(int i)
{
/* ... */
}
int g(double d)
{
/* ... */
}
double h()
{
/* ... */
}
Note that C++ type rules, not C rules, are used. So you can't call function declared ``extern "C"'' with the wrong number of argument. For example:
// C++ code
void more_code(int i, double d)
{
double dd = h(i,d); // error: unexpected arguments
// ...
}
Just declare the C++ function ``extern "C"'' (in your C++ code) and call it (from your C or C++ code). For example:
// C++ code:
extern "C" void f(int);
void f(int i)
{
// ...
}
Now f() can be used like this:
/* C code: */
void f(int);
void cc(int i)
{
f(i);
/* ... */
}
Naturally, this works only for non-member functions. If you want to call member functions (incl. virtual functions) from C, you need to provide a simple wrapper. For example:
// C++ code:
class C {
// ...
virtual double f(int);
};
extern "C" double call_C_f(C* p, int i) // wrapper function
{
return p->f(i);
}
Now C::f() can be used like this:
/* C code: */
double call_C_f(struct C* p, int i);
void ccc(struct C* p, int i)
{
double d = call_C_f(p,i);
/* ... */
}
If you want to call overloaded functions from C, you must provide wrappers with distinct names for the C code to use. For example:
// C++ code:
void f(int);
void f(double);
extern "C" void f_i(int i) { f(i); }
extern "C" void f_d(double d) { f(d); }
Now the f() functions can be used like this:
/* C code: */
void f_i(int);
void f_d(double);
void cccc(int i,double d)
{
f_i(i);
f_d(d);
/* ... */
}
Note that these techniques can be used to call a C++ library from C code even if you cannot (or do not want to) modify the C++ headers.
由于咱是用到c调用c++,暂不关心c++调用c的部分,如上可知,要调用c++类的成员函数,那可是麻烦的麻烦。于是还是乖乖写个函数封装一下类。
由于log4cpp的调用日志比较麻烦,不像log4j,每次都要初始化一大堆东西,于是自己就把这些东西封装成了一个类为Log4cppBase:
Here is code:
Log4cppBase.h
[c-sharp] view plaincopy
#ifndef LOG4CPPBASE_H
#define LOG4CPPBASE_H
#include
#include "log4cpp/Category.hh"
#include "log4cpp/PropertyConfigurator.hh"
#include
/*
* author: Lan Zhihong from xmu soft
*/
class Log4cppBase
{
protected:
Log4cppBase()
{
try{
log4cpp::PropertyConfigurator::configure("log4cpp/log4cpp.conf");
}catch(log4cpp::ConfigureFailure& f)
{
std::cout << "Configure Problem" << f.what() << std::endl;
}
iRoot = &log4cpp::Category::getRoot();
iSub = &log4cpp::Category::getInstance(std::string("sub1"));
}
private:
Log4cppBase& operator=(Log4cppBase&);
Log4cppBase(const Log4cppBase&);
public:
~Log4cppBase();
static Log4cppBase* getInstance();
static std::string vform(const char* format, va_list args);
void info(const std::string& msg);
void debug(const std::string& msg);
void notice(const std::string& msg);
void warn(const std::string& msg);
void error(const std::string& msg);
void crit(const std::string& msg);
void alert(const std::string& msg);
void emerg(const std::string& msg);
void fatal(const std::string& msg);
private:
static Log4cppBase *iInstance;
log4cpp::Category *iSub;
log4cpp::Category *iRoot;
};
#endif
Log4cppBase.cpp
[c-sharp] view plaincopy
#include "Log4cppBase.h"
#include
#include
#define VSNPRINTF vsnprintf
Log4cppBase* Log4cppBase::iInstance = 0;
Log4cppBase::~Log4cppBase()
{
if( iSub != NULL )
{
delete iSub;
iSub = NULL;
}
if( iRoot != NULL)
{
delete iRoot;
iRoot = NULL;
}
if( iInstance != NULL)
{
delete iInstance;
iInstance = NULL;
}
}
Log4cppBase* Log4cppBase::getInstance()
{
if( iInstance == 0)
iInstance = new Log4cppBase();
return iInstance;
}
std::string Log4cppBase::vform(const char* format, va_list args)
{
size_t size = 1024;
char* buffer = new char[size];
while (1) {
int n = VSNPRINTF(buffer, size, format, args);
// If that worked, return a string.
if ((n > -1) && (static_cast(n) < size)) {
std::string s(buffer);
delete [] buffer;
return s;
}
// Else try again with more space.
size = (n > -1) ?
n + 1 : // ISO/IEC 9899:1999
size * 2; // twice the old size
delete [] buffer;
buffer = new char[size];
}
}
void Log4cppBase::info(const std::string& msg)
{
iSub->info(msg);
/*
va_list va;
va_start(va, msg);
iSub->info(vform(msg, va));
va_end(va);
*/
}
void Log4cppBase::debug(const std::string& msg)
{
iSub->info(msg);
}
void Log4cppBase::notice(const std::string& msg)
{
iSub->notice(msg);
}
void Log4cppBase::warn(const std::string& msg)
{
iSub->warn(msg);
}
void Log4cppBase::error(const std::string& msg)
{
iSub->error(msg);
}
void Log4cppBase::crit(const std::string& msg)
{
iSub->crit(msg);
}
void Log4cppBase::alert(const std::string& msg)
{
iSub->alert(msg);
}
void Log4cppBase::emerg(const std::string& msg)
{
iSub->emerg(msg);
}
void Log4cppBase::fatal(const std::string& msg)
{
iSub->fatal(msg);
}
/*
int main(int argc, char** argv)
{
Log4cppBase* instance = Log4cppBase::getInstance();
int i = 5;
instance->info("hello world");
return 0;
}
*/
由于选择了调用c++的非成员函数,于是由添加了这样的一个类Log4cppUtil
Here is code:
Log4cppUtil.h
[c-sharp] view plaincopy
#ifdef _cplusplus
extern "C"
{
#endif
void log4cpp_info(const char *msg, ...);
#ifdef _cplusplus
}
#endif
#ifdef _cplusplus
extern "C"
{
#endif
void log4cpp_debug(const char *msg, ...);
#ifdef _cplusplus
}
#endif
#ifdef _cplusplus
extern "C"
{
#endif
void log4cpp_notice(const char *msg, ...);
#ifdef _cplusplus
}
#endif
#ifdef _cplusplus
extern "C"
{
#endif
void log4cpp_warn(const char *msg, ...);
#ifdef _cplusplus
}
#endif
#ifdef _cplusplus
extern "C"
{
#endif
void log4cpp_error(const char *msg, ...);
#ifdef _cplusplus
}
#endif
#ifdef _cplusplus
extern "C"
{
#endif
void log4cpp_crit(const char *msg, ...);
#ifdef _cplusplus
}
#endif
#ifdef _cplusplus
extern "C"
{
#endif
void log4cpp_alert(const char *msg, ...);
#ifdef _cplusplus
}
#endif
#ifdef _cplusplus
extern "C"
{
#endif
void log4cpp_emerg(const char *msg, ...);
#ifdef _cplusplus
}
#endif
#ifdef _cplusplus
extern "C"
{
#endif
void log4cpp_fatal(const char *msg, ...);
#ifdef _cplusplus
}
#endif
Log4cppUtil.cpp
[c-sharp] view plaincopy
#ifndef _cplusplus
#define _cplusplus
#endif
#include "Log4cppBase.h"
#include "Log4cppUtil.h"
void log4cpp_info(const char* msg, ...)
{
Log4cppBase * instance = Log4cppBase::getInstance();
va_list va;
va_start(va, msg);
instance->info(instance->vform(msg,va));
va_end(va);
}
void log4cpp_debug(const char* msg, ...)
{
Log4cppBase * instance = Log4cppBase::getInstance();
va_list va;
va_start(va, msg);
instance->debug(instance->vform(msg,va));
va_end(va);
}
void log4cpp_notice(const char* msg, ...)
{
Log4cppBase * instance = Log4cppBase::getInstance();
va_list va;
va_start(va, msg);
instance->notice(instance->vform(msg,va));
va_end(va);
}
void log4cpp_warn(const char* msg, ...)
{
Log4cppBase * instance = Log4cppBase::getInstance();
va_list va;
va_start(va, msg);
instance->warn(instance->vform(msg,va));
va_end(va);
}
void log4cpp_error(const char* msg, ...)
{
Log4cppBase * instance = Log4cppBase::getInstance();
va_list va;
va_start(va, msg);
instance->error(instance->vform(msg,va));
va_end(va);
}
void log4cpp_crit(const char* msg, ...)
{
Log4cppBase * instance = Log4cppBase::getInstance();
va_list va;
va_start(va, msg);
instance->crit(instance->vform(msg,va));
va_end(va);
}
void log4cpp_alert(const char* msg, ...)
{
Log4cppBase * instance = Log4cppBase::getInstance();
va_list va;
va_start(va, msg);
instance->alert(instance->vform(msg,va));
va_end(va);
}
void log4cpp_emerg(const char* msg, ...)
{
Log4cppBase * instance = Log4cppBase::getInstance();
va_list va;
va_start(va, msg);
instance->emerg(instance->vform(msg,va));
va_end(va);
}
void log4cpp_fatal(const char* msg, ...)
{
Log4cppBase * instance = Log4cppBase::getInstance();
va_list va;
va_start(va, msg);
instance->fatal(instance->vform(msg,va));
va_end(va);
}
然后再在自己的C代码中调用这个Log4cppUtil,我用的测试代码test.c如下:
[c-sharp] view plaincopy
#include
#include "Log4cppUtil.h"
extern void log4cpp_info(const char *msg, ...);
extern void log4cpp_debug(const char *msg, ...);
extern void log4cpp_notice(const char *msg, ...);
extern void log4cpp_warn(const char *msg, ...);
extern void log4cpp_error(const char *msg, ...);
extern void log4cpp_crit(const char *msg, ...);
extern void log4cpp_alert(const char *msg, ...);
extern void log4cpp_emerg(const char *msg, ...);
extern void log4cpp_fatal(const char *msg, ...);
int main()
{
int i = 3;
log4cpp_info("hello: %d", i);
log4cpp_debug("hello: %d", i);
log4cpp_notice("hello: %d", i);
log4cpp_warn("hello: %d", i);
log4cpp_error("hello: %d", i);
log4cpp_crit("hello: %d", i);
log4cpp_alert("hello: %d", i);
log4cpp_emerg("hello: %d", i);
log4cpp_fatal("hello: %d", i);
return 0;
}
在C代码中要用extern告诉编译器,这个函数在其他文件
在Linux命令行编译如下:
1、编译Log4cppBase,由于我在本机上已经安装Log4cpp的库到了/use/lib下,所以可以不用置顶库的路径,直接按下面代码编译
g++ -fpic -llog4cpp -shared -g -o liblog4cppbase.so Log4cppBase.cpp
2、编译Log4cppUtil,由于Log4cppUtil需要用到Log4cppBase,因此需要置顶库的搜索路径为当前路径./
g++ -fpic -shared -g -o liblog4cpputil.so Log4cppUtil.cpp -I ./
3、编译自己写的test.c,生成可执行文件,在此需要把上面编译的两个库文件全部加进去,编译成可执行文件
gcc -o test test.c ./liblog4cpputil.so ./liblog4cppbase.so
编译成功!晚上赏自己个鸡腿吃!
以上是在PC机子上的编译
交叉编译进板子的话按上面那个方法是行不通的,因为系统找不到Log4cpp的库或者其他库等,可以参考前面我转载的一篇文章《【开发工具面】GCC命令行详解》,而我是把log4cpp交叉编译到/use/local下面去,而我自己的/usr下面也有一个PC版本的log4cpp,因此要注意调用哪一个命令,因此使用绝对路径/usr/local/bin/log4cpp-config
重新修改命令,如下:
arm-linux-g++ -fpic -shared `/usr/local/bin/log4cpp-config --libs --cflags` -o liblog4cppbase.so Log4cppBase.cpp
arm-linux-g++ -fpic -shared `/usr/local/bin/log4cpp-config --libs --cflags` -o liblog4cpputil.so Log4cppUtil.cpp -I./
arm-linux-gcc `/usr/local/bin/log4cpp-config --libs --cflags` -o test test.c log4cpp/liblog4cppbase.so log4cpp/liblog4cpputil.so
编译成功,移植到开发板上去,成功跑起来!
阅读(1001) | 评论(0) | 转发(0) |