[C++-sig] Re: Creating an instance of a python class derived from a C++ object from C++
David Abrahams
dave at boost-consulting.com
Sat Jul 10 21:47:03 CEST 2004
Brian Hall <bhall at midwaygames.com> writes:
> Hello all,
>
> Say I have the following:
>
> class MyCppClass
> {
> public:
> virtual int SomeFunction(void) = 0;
> };
>
> struct MyCppClassWrap : public MyCppClass
> {
> MyCppClassWrap(PyObject *self_)
> : self(self_)
> {}
> int SomeFunction(void) { return call_method<int>(self, "some_function"); }
>
> PyObject *self;
> };
>
> int call_SomeFunction(MyCppClass &c) { return c.SomeFunction(); }
>
> BOOST_PYTHON_MODULE(MyPythonModule)
> {
> class_<cState>("State", init<std::string>())
> .def("value", &cState::Value)
> .def("set_value", &cState::SetValue)
> .def("initial_value", &cState::InitialValue)
> .def("set_initial_value", &cState::SetInitialValue)
> .def("name", &cState::Name)
> .def("reset", &cState::Reset)
> .def("iterate", &cState::Iterate)
> ;
> def("call_some_function", call_SomeFunction);
> };
>
> Now say I want to dynamically create an instance of a python class derived
> from MyCppClass like so:
>
> class MyPythonClass(MyCppClass):
> def SomeFunction(self):
> return 42
>
> But I want to do this from C++, not Python... how would I do this?
Use the metaclass interface:
>>> class fu(object):pass
...
>>> bases = (fu,)
>>> attributes = { 'x' : 1, 'quack' : lambda self: 'like a duck' }
>>> bar = object.__class__('bar', bases, attributes) # a derived class of fu
>>> help(bar)
Help on class bar in module __main__:
class bar(fu)
| Method resolution order:
| bar
| fu
| __builtin__.object
|
| Methods defined here:
|
| lambdaself
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| x = 1
|
| ----------------------------------------------------------------------
| Data and other attributes inherited from fu:
|
| __dict__ = <dictproxy object>
| dictionary for instance variables (if defined)
|
| __weakref__ = <attribute '__weakref__' of 'fu' objects>
| list of weak references to the object (if defined)
>>> bar().quack()
'like a duck'
>>> bar.x
1
So,
object py_cState; // the Python class object
BOOST_PYTHON_MODULE(MyPythonModule)
{
py_cState = class_<cState>("State", init<std::string>())
^^^^^^^^^^^^
.def("value", &cState::Value)
.def("set_value", &cState::SetValue)
.def("initial_value", &cState::InitialValue)
.def("set_initial_value", &cState::SetInitialValue)
.def("name", &cState::Name)
.def("reset", &cState::Reset)
.def("iterate", &cState::Iterate)
;
def("call_some_function", call_SomeFunction);
};
char const* quack(object self) { return "like a duck"; }
// returns a new class
object make_bar
{
object bases = make_tuple(py_cState);
dict attributes;
attributes['x'] = 1;
attributes['quack'] = quack;
return py_cState.attr("__class__")("bar", bases, attributes);
};
> Basically
> I want to be able to define new Python derived types of MyCppClass at runtime
> on the fly, and redefine them at will. Say for instance the user of the
> application typed in the above declaration of MyPythonClass... and then later,
> updated that definition to return 43 instead, I want to be able to redefine
> the code for the class... if I did that, would I have to destroy the old
> instance and create a new one? Any ideas?
You can always replace the class' methods one-at-a-time.
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
More information about the Cplusplus-sig
mailing list