Boost logo

Boost :

Subject: [boost] Is there any interest in a library which solves C++ class reflection feature just like Java does?
From: jinhua luo (ljh.home.king_at_[hidden])
Date: 2011-12-05 20:40:36


Hi,

In brief, I'd designed and implemented somehow C++ class reflection based
on boost libraries.
It has some unique advantages:
a) it doesn't require code generator
b) platform independent and compiler independent (I tested it on Windows
and Linux, with vs2008 and gcc respectively)
c) it's non-intrusive for the class definition, instead, you just need to
declare and describe your class via some straightforward macros anywhere
(header file or source file, and may be within any namespace), which also
means you can wrap an external third-party library (which you have no way
to touch the source codes) and reflects it classes.
d) Cross shared library boundary, you can dynamic load the shared library
and reflect the classes within it, without need to export any symbol
manunally in C wrapper function way
e) the API looks like Java reflection API

Below is some codes snippet to have an overview of this library:
-----libTest.cpp---start---
#include <iostream>
#include <string>

#include <boost/reflection/reflection.hpp>

namespace test {

class AccountItf {
public:
    virtual std::string getId() const = 0;
    virtual void setId(std::string id) = 0;
};

#define ACCOUNT_INTERFACE_REFL_DECLARE \
    BOOST_REFL_INTERFACE(test::AccountItf) \
    BOOST_REFL_CONST_METHOD(getId, std::string()) \
    BOOST_REFL_METHOD(setId, void(std::string))

class Account : public AccountItf {
    std::string id;
public:
    Account() : age(0) {}
    Account(std::string id, unsigned int age) : id(id), age(age) {}
    static void echo(Account* acct, std::string banner) {
        std::cout << banner + ": " << acct->getId() << std::endl;
    }
    std::string getId() const {
        return id;
    }
    void setId(std::string id) {
        this->id = id;
    }
public:
    unsigned int age;
};

//Account declaration for used by reflection
//this declaration can be placed anywhere, even the header file
BOOST_REFL_CLASS (
    (test)(Account),
    //constructors
    BOOST_REFL_CONSTRUCTOR()
    BOOST_REFL_CONSTRUCTOR(std::string id, unsigned int age)
    //static methods
    BOOST_REFL_STATIC_METHOD(echo, void (Account* acct, std::string banner))
    //properties
    BOOST_REFL_PROPERTY(age, unsigned int)
    //derived Inteface
    ACCOUNT_INTERFACE_REFL_DECLARE
)
}

-----libTest.cpp----end--
Compile the libTest.cpp into the libTest.dll or libTest.so.

-----main.cpp----start--
#include <iostream>
#include <string>
using namespace std;

#include <boost/reflection/reflection.hpp>
using namespace boost::reflection;

#if defined(BOOST_WINDOWS)
#include <Windows.h>
#else
#include <dlfcn.h>
#endif

int main(int argc, char* argv[])
{
#if defined(BOOST_WINDOWS)
    LoadLibraryA (argv[1]);
#else
    dlopen(argv[1], RTLD_NOW);
#endif
    Class t = Class::forName("test.Account");

    boost::any obj = t.newInstance(std::string("Account-id-100"), (unsigned
int)26);

    t.invokeStatic("echo", obj, std::string("TEST"));

    TypeInfoArray tArray;
    tArray.push_back(BOOST_REFL_TYPEID(std::string));
    Method m1 = t.getMethod("setId", tArray);
    m1.invoke(obj, std::string("Account-id-200"));

    Method m2 = t.getMethod("getId");
    boost::any ret = m2.invoke(obj);
    std::cout << "Account getId(): " << boost::any_cast<std::string>(ret)
<< std::endl;

    Property prop = t.getProperty("age");
    prop.set(obj, (unsigned int)30);
    std::cout << "Account age: " << boost::any_cast<unsigned
int>(prop.get(obj)) << std::endl;

    return 0;
}
-----main.cpp---end---

Compile the main.cpp into the executable and execute it:
./main libTest.dll

it will output:
TEST: Account-id-100
Account getId(): Account-id-200
Account age: 30

This library is very useful for framework-level design which needs C++
reflection, e.g. recently I'm working on somehow SQL mapping library for
C++, just like MyBatis, and reflection makes possible to invoke the
getter/setter of the object instances of classes specified in the XML file.

Regards,
JinHua


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk