Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1815867
  • 博文数量: 473
  • 博客积分: 13997
  • 博客等级: 上将
  • 技术积分: 5953
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-22 11:52
文章分类

全部博文(473)

文章存档

2014年(8)

2013年(38)

2012年(95)

2011年(181)

2010年(151)

分类: LINUX

2012-09-03 16:02:01

由于要使用到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

 

 

编译成功,移植到开发板上去,成功跑起来!
阅读(921) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~