[C++-sig] Function handling with Boost

Stefan Seefeld seefeld at sympatico.ca
Tue Jun 23 23:00:21 CEST 2009


On 06/23/2009 04:43 PM, Christopher Schramm wrote:
> Stefan Seefeld wrote:
>    
>> You need a module into which to inject the symbols you export. That is
>> true no matter the (meta)type of what you export, i.e. classes,
>> functions, etc.
>> Once you have that module set up (via BOOST_PYTHON_MODULE), you can
>> instantiate the newly created Python objects (types) from within C++
>> code, without having to go through the interpreter, import, eval, or exec.
>>      
>
> So you say I may use BOOST_PYTHON_MODULE to define a module and then
> immediately work with it? Hm - I failed with that at my very first try.
>
> What I did was using BOOST_PYTHON_MODULE and after that calling bpy's
> import() to add it to my global namespace what failed due to not finding
> the module.
>    

An alternative is not to use BOOST_PYTHON_MODULE at all, but set up 
converters in ordinary C++ code. In the following I set up a Python 
interpreter in my main application, inject a (C++) base class, run a 
Python script that adds a derived class, then instantiate and run that 
derived class from C++ code. I this may just be what you want:

------------------------------

namespace bpl = boost::python;

// An abstract base class
class Base : public boost::noncopyable
{
public:
   virtual ~Base() {};
   virtual std::string hello() = 0;
};

// Familiar Boost.Python wrapper class for Base
struct BaseWrap : Base, bpl::wrapper<Base>
{
   virtual std::string hello()
   {
     return this->get_override("hello")();
   }
};

int main(int, char **)
{
   Py_Initialize();

   // Install C++ <-> Python converters
   bpl::class_<BaseWrap, boost::noncopyable> base("Base");

   // Retrieve the main module
   bpl::object main = bpl::import("__main__");
   // Retrieve the main module's namespace
   bpl::object global(main.attr("__dict__"));
   // Inject 'Base' type into global dict
   global["Base"] = base;
   try
   {
     // Run script
     bpl::exec_file("exec.py", global, global);
     // Extract 'Derived' class, and instantiate it
     bpl::object derived = global["Derived"]();
     // Extract reference-to-base-class
     Base &d = bpl::extract<Base &>(derived);
     // Call 'hello'
     std::cout << d.hello() << std::endl;
   }
   catch (bpl::error_already_set const &)
   {
       PyErr_Print();
   }
}


------------------------------
And the Python side:
------------------------------

class Derived(Base):

     def hello(self): return 'Hello from Python !'

------------------------------

Easy, isn't it ?

Regards,
         Stefan

-- 

       ...ich hab' noch einen Koffer in Berlin...



More information about the Cplusplus-sig mailing list