#ifndef CLASS_WRAPPER_DWA101000_H_ # define CLASS_WRAPPER_DWA101000_H_ #include "extclass.h" #include "operators.h" #include "module.h" #include "py.h" #include "cast.h" #include "pyptr.h" namespace python { // Syntactic sugar to make wrapping classes more convenient template > class class_builder : python_extension_class_converters // Works around MSVC6.x/GCC2.95.2 bug described below { public: class_builder(module_builder& module, const char* name) : m_class(new detail::extension_class(name)) { module.add(ref(as_object(m_class.get()), ref::increment_count), name); } ~class_builder() {} // define constructors template void def(const signature& signature) { m_class->def(signature); } // export heterogeneous reverse-argument operators // (type of lhs: 'left', of rhs: 'right') // usage: foo_class.def(python::operators<(python::op_add | python::op_sub), Foo>(), // python::left_operand()); template void def(operators o1, left_operand o2) { m_class->def(o1, o2); } // export heterogeneous operators (type of lhs: 'left', of rhs: 'right') // usage: foo_class.def(python::operators<(python::op_add | python::op_sub), Foo>(), // python::right_operand()); template void def(operators o1, right_operand o2) { m_class->def(o1, o2); } // define a function that passes Python arguments and keywords // to C++ verbatim (as a 'tuple const &' and 'dictionary const &' // respectively). This is useful for manual argument passing. // It's also the only possibility to pass keyword arguments to C++. // Fn must have a signatur that is compatible to // PyObject * (*)(PyObject * aTuple, PyObject * aDictionary) template void def_raw(Fn fn, const char* name) { m_class->def_raw(fn, name); } // define member functions. In fact this works for free functions, too - // they act like static member functions, or if they start with the // appropriate self argument (as a pointer or reference), they can be used // just like ordinary member functions -- just like Python! template void def(Fn fn, const char* name) { m_class->def(fn, name); } // Define a virtual member function with a default implementation. // default_fn should be a function which provides the default implementation. // Be careful that default_fn does not in fact call fn virtually! template void def(Fn fn, const char* name, DefaultFn default_fn) { m_class->def(fn, name, default_fn); } // Provide a function which implements x., reading from the given // member (pm) of the T obj template void def_getter(MemberType T::*pm, const char* name) { m_class->def_getter(pm, name); } // Provide a function which implements assignment to x., writing to // the given member (pm) of the T obj template void def_setter(MemberType T::*pm, const char* name) { m_class->def_getter(pm, name); } // Expose the given member (pm) of the T obj as a read-only attribute template void def_readonly(MemberType T::*pm, const char* name) { m_class->def_readonly(pm, name); } // Expose the given member (pm) of the T obj as a read/write attribute template void def_read_write(MemberType T::*pm, const char* name) { m_class->def_read_write(pm, name); } // define the standard coercion needed for operator overloading void def_standard_coerce() { m_class->def_standard_coerce(); } // declare the given class a base class of this one and register // conversion functions template void declare_base(class_builder const & base) { m_class->declare_base(base.get_extension_class()); } // declare the given class a base class of this one and register // upcast conversion function template void declare_base(class_builder const & base, without_downcast_t) { m_class->declare_base(base.get_extension_class(), without_downcast); } // get the embedded ExtensioClass object detail::extension_class * get_extension_class() const { return m_class.get(); } // set an arbitrary attribute. Useful for non-function class data members, // e.g. enums void add(PyObject* x, const char* name) { m_class->set_attribute(name, x); } void add(ref x, const char* name) { m_class->set_attribute(name, x); } private: // declare the given class a base class of this one and register // conversion functions template void declare_base(detail::extension_class * base) { m_class->declare_base(base); } // declare the given class a base class of this one and register // upcast conversion function template void declare_base(detail::extension_class * base, without_downcast_t) { m_class->declare_base(base, without_downcast); } reference > m_class; }; // The bug mentioned at the top of this file is that on certain compilers static // global functions declared within the body of a class template will only be // generated when the class template is constructed, and when (for some reason) // the construction does not occur via a new-expression. Otherwise, we could // rely on the initialization of the m_class data member to cause all of the // to_/from_python functions to come into being. } #endif // CLASS_WRAPPER_DWA101000_H_