Linux混合編程+log4cpp

來源:互聯網
上載者:User

 

     由於要使用到log4cpp的庫,而log4c的資料是非常的少,也懶得去研究它的用法,於是就決定試試混合編程者玩意。

      首先先引用下C++它的father: Stroustrup的一篇文章《C++ Style and Technique FAQ》(http://www2.research.att.com/~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++ codeextern "C" void f(int);// one wayextern "C" {// another wayint 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++ codevoid 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

 

#ifndef LOG4CPPBASE_H<br />#define LOG4CPPBASE_H<br />#include <iostream><br />#include "log4cpp/Category.hh"<br />#include "log4cpp/PropertyConfigurator.hh"<br />#include <stdarg.h><br />/*<br />*author: Lan Zhihong from xmu soft<br />*/<br />class Log4cppBase<br />{<br />protected:<br />Log4cppBase()<br />{<br />try{<br />log4cpp::PropertyConfigurator::configure("log4cpp/log4cpp.conf");<br />}catch(log4cpp::ConfigureFailure& f)<br />{<br />std::cout << "Configure Problem" << f.what() << std::endl;<br />}<br />iRoot = &log4cpp::Category::getRoot();<br />iSub = &log4cpp::Category::getInstance(std::string("sub1"));</p><p>}<br />private:<br />Log4cppBase& operator=(Log4cppBase&);<br />Log4cppBase(const Log4cppBase&);</p><p>public:<br />~Log4cppBase();<br />static Log4cppBase* getInstance();<br />static std::string vform(const char* format, va_list args);<br />void info(const std::string& msg);<br />void debug(const std::string& msg);<br />void notice(const std::string& msg);<br />void warn(const std::string& msg);<br />void error(const std::string& msg);<br />void crit(const std::string& msg);<br />void alert(const std::string& msg);<br />void emerg(const std::string& msg);<br />void fatal(const std::string& msg);<br />private:<br />static Log4cppBase *iInstance;<br />log4cpp::Category *iSub;<br />log4cpp::Category *iRoot;<br />};<br />#endif

 

 

Log4cppBase.cpp

 

 

 #include "Log4cppBase.h"<br />#include <sstream><br />#include <stdio.h><br />#define VSNPRINTF vsnprintf</p><p>Log4cppBase* Log4cppBase::iInstance = 0;<br />Log4cppBase::~Log4cppBase()<br />{<br />if( iSub != NULL )<br />{<br />delete iSub;<br />iSub = NULL;<br />}<br />if( iRoot != NULL)<br />{<br />delete iRoot;<br />iRoot = NULL;<br />}<br />if( iInstance != NULL)<br />{<br />delete iInstance;<br />iInstance = NULL;<br />}<br />}<br />Log4cppBase* Log4cppBase::getInstance()<br />{<br />if( iInstance == 0)<br />iInstance = new Log4cppBase();<br />return iInstance;<br />}<br />std::string Log4cppBase::vform(const char* format, va_list args)<br />{<br />size_t size = 1024;<br />char* buffer = new char[size];</p><p>while (1) {<br /> int n = VSNPRINTF(buffer, size, format, args);</p><p> // If that worked, return a string.<br /> if ((n > -1) && (static_cast<size_t>(n) < size)) {<br />std::string s(buffer);<br />delete [] buffer;<br />return s;<br /> }</p><p> // Else try again with more space.<br /> size = (n > -1) ?<br /> n + 1 : // ISO/IEC 9899:1999<br /> size * 2; // twice the old size</p><p> delete [] buffer;<br /> buffer = new char[size];<br />}<br />}<br />void Log4cppBase::info(const std::string& msg)<br />{<br />iSub->info(msg);<br />/*<br />va_list va;<br />va_start(va, msg);<br />iSub->info(vform(msg, va));<br />va_end(va);<br />*/<br />}<br />void Log4cppBase::debug(const std::string& msg)<br />{<br />iSub->info(msg);<br />}<br />void Log4cppBase::notice(const std::string& msg)<br />{<br />iSub->notice(msg);<br />}<br />void Log4cppBase::warn(const std::string& msg)<br />{<br />iSub->warn(msg);<br />}<br />void Log4cppBase::error(const std::string& msg)<br />{<br />iSub->error(msg);<br />}<br />void Log4cppBase::crit(const std::string& msg)<br />{<br />iSub->crit(msg);<br />}<br />void Log4cppBase::alert(const std::string& msg)<br />{<br />iSub->alert(msg);<br />}<br />void Log4cppBase::emerg(const std::string& msg)<br />{<br />iSub->emerg(msg);<br />}<br />void Log4cppBase::fatal(const std::string& msg)<br />{<br />iSub->fatal(msg);<br />}<br />/*<br />int main(int argc, char** argv)<br />{<br />Log4cppBase* instance = Log4cppBase::getInstance();<br />int i = 5;<br />instance->info("hello world");<br />return 0;<br />}<br />*/

 

 

由於選擇了調用c++的非成員函數,於是由添加了這樣的一個類Log4cppUtil

 

Here is code:

 

Log4cppUtil.h

 

#ifdef _cplusplus<br />extern "C"<br />{<br />#endif<br />void log4cpp_info(const char *msg, ...);<br />#ifdef _cplusplus<br />}<br />#endif<br />#ifdef _cplusplus<br />extern "C"<br />{<br />#endif<br />void log4cpp_debug(const char *msg, ...);<br />#ifdef _cplusplus<br />}<br />#endif<br />#ifdef _cplusplus<br />extern "C"<br />{<br />#endif<br />void log4cpp_notice(const char *msg, ...);<br />#ifdef _cplusplus<br />}<br />#endif<br />#ifdef _cplusplus<br />extern "C"<br />{<br />#endif<br />void log4cpp_warn(const char *msg, ...);<br />#ifdef _cplusplus<br />}<br />#endif<br />#ifdef _cplusplus<br />extern "C"<br />{<br />#endif<br />void log4cpp_error(const char *msg, ...);<br />#ifdef _cplusplus<br />}<br />#endif<br />#ifdef _cplusplus<br />extern "C"<br />{<br />#endif<br />void log4cpp_crit(const char *msg, ...);<br />#ifdef _cplusplus<br />}<br />#endif<br />#ifdef _cplusplus<br />extern "C"<br />{<br />#endif<br />void log4cpp_alert(const char *msg, ...);<br />#ifdef _cplusplus<br />}<br />#endif<br />#ifdef _cplusplus<br />extern "C"<br />{<br />#endif<br />void log4cpp_emerg(const char *msg, ...);<br />#ifdef _cplusplus<br />}<br />#endif<br />#ifdef _cplusplus<br />extern "C"<br />{<br />#endif<br />void log4cpp_fatal(const char *msg, ...);<br />#ifdef _cplusplus<br />}<br />#endif<br />

 

Log4cppUtil.cpp

 

 

#ifndef _cplusplus<br />#define _cplusplus<br />#endif<br />#include "Log4cppBase.h"<br />#include "Log4cppUtil.h"</p><p>void log4cpp_info(const char* msg, ...)<br />{<br />Log4cppBase * instance = Log4cppBase::getInstance();<br />va_list va;<br />va_start(va, msg);<br />instance->info(instance->vform(msg,va));<br />va_end(va);<br />}<br />void log4cpp_debug(const char* msg, ...)<br />{<br />Log4cppBase * instance = Log4cppBase::getInstance();<br />va_list va;<br />va_start(va, msg);<br />instance->debug(instance->vform(msg,va));<br />va_end(va);<br />}<br />void log4cpp_notice(const char* msg, ...)<br />{<br />Log4cppBase * instance = Log4cppBase::getInstance();<br />va_list va;<br />va_start(va, msg);<br />instance->notice(instance->vform(msg,va));<br />va_end(va);<br />}<br />void log4cpp_warn(const char* msg, ...)<br />{<br />Log4cppBase * instance = Log4cppBase::getInstance();<br />va_list va;<br />va_start(va, msg);<br />instance->warn(instance->vform(msg,va));<br />va_end(va);<br />}<br />void log4cpp_error(const char* msg, ...)<br />{<br />Log4cppBase * instance = Log4cppBase::getInstance();<br />va_list va;<br />va_start(va, msg);<br />instance->error(instance->vform(msg,va));<br />va_end(va);<br />}<br />void log4cpp_crit(const char* msg, ...)<br />{<br />Log4cppBase * instance = Log4cppBase::getInstance();<br />va_list va;<br />va_start(va, msg);<br />instance->crit(instance->vform(msg,va));<br />va_end(va);<br />}<br />void log4cpp_alert(const char* msg, ...)<br />{<br />Log4cppBase * instance = Log4cppBase::getInstance();<br />va_list va;<br />va_start(va, msg);<br />instance->alert(instance->vform(msg,va));<br />va_end(va);<br />}<br />void log4cpp_emerg(const char* msg, ...)<br />{<br />Log4cppBase * instance = Log4cppBase::getInstance();<br />va_list va;<br />va_start(va, msg);<br />instance->emerg(instance->vform(msg,va));<br />va_end(va);<br />}<br />void log4cpp_fatal(const char* msg, ...)<br />{<br />Log4cppBase * instance = Log4cppBase::getInstance();<br />va_list va;<br />va_start(va, msg);<br />instance->fatal(instance->vform(msg,va));<br />va_end(va);<br />}

 

然後再在自己的C代碼中調用這個Log4cppUtil,我用的測試代碼test.c如下:

 

 

#include <stdio.h><br />#include "Log4cppUtil.h"<br />extern void log4cpp_info(const char *msg, ...);<br />extern void log4cpp_debug(const char *msg, ...);<br />extern void log4cpp_notice(const char *msg, ...);<br />extern void log4cpp_warn(const char *msg, ...);<br />extern void log4cpp_error(const char *msg, ...);<br />extern void log4cpp_crit(const char *msg, ...);<br />extern void log4cpp_alert(const char *msg, ...);<br />extern void log4cpp_emerg(const char *msg, ...);<br />extern void log4cpp_fatal(const char *msg, ...);</p><p>int main()<br />{<br />int i = 3;<br />log4cpp_info("hello: %d", i);<br />log4cpp_debug("hello: %d", i);<br />log4cpp_notice("hello: %d", i);<br />log4cpp_warn("hello: %d", i);<br />log4cpp_error("hello: %d", i);<br />log4cpp_crit("hello: %d", i);<br />log4cpp_alert("hello: %d", i);<br />log4cpp_emerg("hello: %d", i);<br />log4cpp_fatal("hello: %d", i);<br />return 0;<br />}

 

在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

 

 

編譯成功,移植到開發板上去,成功跑起來!


 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.