Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Boost.Reflection/Boost.Extension Interoperability

Reflections are designed to work with Boost.Extension, or with shared libraries in general. A simple example is included in examplesextension.

Declaring the reflected class itself is similar to the process for doing the same in Boost.Extension.

Here's how the Jamfile for these libraries is defined. Note that, like in Boost.Extension, one can rename the shared library extensions, for consistency across platforms. Here, we use the .reflection suffix for each shared library.

import type : change-generated-target-suffix ;
import type : change-generated-target-prefix ;
type.change-generated-target-suffix SHARED_LIB : : reflection ;
type.change-generated-target-prefix SHARED_LIB : : lib ;
exe extension-reflection : extension/extension.cpp ;
lib car_lib : extension/car_lib.cpp : <link>shared ;

The code in the shared library is defined in libs/reflection/examples/extension/car_lib.cpp.

We define two classes to export as reflections. Note that they are not derived from the same base class. If we were using Boost.Extension factories, this would be required.

class suv
{
public:
        suv(const char * name) : car(name) {}
        const char * get_type(void) { return "It's an SUV."; }
        ~suv(void) {}
};

class compact
{
public:
        compact(const char * name) : car(name) {}
        const char * get_type(void) { return "It's a compact."; }
        ~compact(void) {}
};

Just like Boost.Extension, an external function needs to be defined that will be called by the main module.

extern "C" void BOOST_EXTENSION_EXPORT_DECL extension_export_car(std::map<std::string, reflection> reflection_map) { reflection_map“suv"” .reflect<suv>() .constructor<const char*>() .function(&suv::get_type, "get_type"); reflection_map“suv"” .reflect<compact>() .constructor<const char*>() .function(&compact::get_type, "get_type"); }

This is all that is necessary to export one constructor and one function for each class.

Now, in extension.cpp, we combine Boost.Extension and Boost.Reflection code to load and use the reflections declared in the shared library.

Create a mapping of reflections to strings that will be populated inside the shared library.

std::map<std::string, reflection> reflection_map;

Load the shared library using Boost.Extension.

boost::extensions::shared_library lib
  ((std::string(BOOST_EXTENSION_DIR_START) +
   "libcar_lib.extension").c_str());
lib.open();

Call an exported function to populate reflection_map.

lib.get<void, std::map<std::string, 
  reflection> &>
  ("extension_export_car")(reflection_map);
if (reflection_map.size() != size_t(2)) {
  std::cout << "Could not load reflections!";
  return 1;
}

Pull out two reflections that were named "suv" and "compact" respectively.

reflection & first_reflection =
  reflection_map["suv"];
reflection & second_reflection =
  reflection_map["compact"];

Use the get_constructor function to find a constructor that takes one argument, a const char*.

instance_constructor<const char *> first_constructor =
  first_reflection.get_constructor<const char *>();

Use the constructor retrieved to create an instance. Warning! instances should only be used with functions and constructors generated by a single reflection object.

instance first_instance = 
  first_constructor("First Instance");

Get a function to call on this instance.

boost::reflections::function<const char *> first_function =
  first_reflection.get_function<const char *>("get_type");
std::cout << "First reflection: " << first_function(first_instance)
          << std::endl;
 

Repeat the steps for the second reflection.

instance_constructor<const char *> second_constructor =
  second_reflection.get_constructor<const char *>();
instance second_instance = 
  second_constructor("Second Instance");
boost::reflections::function<const char *> second_function =
  second_reflection.get_function<const char *>("get_type");
std::cout << "Second reflection: " << second_function(second_instance)
          << std::endl;


PrevUpHomeNext