diff --git a/include/boost/python/x_class_builder.hpp b/include/boost/python/x_class_builder.hpp deleted file mode 100644 index 4b3da600..00000000 --- a/include/boost/python/x_class_builder.hpp +++ /dev/null @@ -1,361 +0,0 @@ -#ifndef X_CLASS_BUILDER_HPP -# define X_CLASS_BUILDER_HPP - -# include - -//QUESTIONMARK -// Do we really need the special PyCvtsObject? -// Is there a better way of creating the special PyCvtsObject? -// My solution adds a lot of code including several reinterpret_cast. -//#define SPECIAL_PYCVTSOBJECT - -namespace boost { namespace python { - struct import_error : error_already_set {}; - struct export_error : error_already_set {}; -}} - -namespace boost { namespace python { namespace detail { - -// Concept: throw exception if api_major is changed -// show warning on stderr if api_minor is changed -const int EXPORT_CONVERTERS_API_MAJOR = 1; -const int EXPORT_CONVERTERS_API_MINOR = 1; -const std::string converters_attribute_name = "__converters__"; -#ifndef SPECIAL_PYCVTSOBJECT -void *import_converters(const std::string& module_name, - const std::string& klass_name, - const std::string& attribute_name); -#else -PyObject *new_import_converters(const std::string& module_name, - const std::string& klass_name, - const std::string& attribute_name); -#endif -void check_export_converters_api(const int importing_major, - const int importing_minor, - const int imported_major, - const int imported_minor); - -}}} - -// forward declaration -namespace boost { namespace python { namespace detail { -template class import_extension_class; -}}} - -BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE - -//QUESTIONMARK -// This class is a look-alike of class python_extension_class_converters. -// Is there a way to ensure that the siblings stay in sync? -template -class python_import_extension_class_converters -{ - public: - - friend python_import_extension_class_converters py_extension_class_converters(boost::python::type) - { - return python_import_extension_class_converters(); - } - - PyObject* to_python(const T& x) const - { - return boost::python::detail::import_extension_class::get_converters()->to_python(x); - } - - friend T* from_python(PyObject* obj, boost::python::type) - { - return boost::python::detail::import_extension_class::get_converters()->Tptr_from_python(obj); - } - - // Convert to const T* - friend const T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to const T* const& - friend const T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T* const& - friend T* from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T& - friend T& from_python(PyObject* p, boost::python::type) - { return *boost::python::detail::check_non_null(from_python(p, boost::python::type())); } - - // Convert to const T& - friend const T& from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - // Convert to T - friend const T& from_python(PyObject* p, boost::python::type) - { return from_python(p, boost::python::type()); } - - friend std::auto_ptr& from_python(PyObject* p, boost::python::type&>) { - return boost::python::detail::import_extension_class::get_converters()->auto_ptr_from_python(p); - } - - friend std::auto_ptr& from_python(PyObject* p, boost::python::type >) { - return boost::python::detail::import_extension_class::get_converters()->auto_ptr_from_python(p); - } - - friend const std::auto_ptr& from_python(PyObject* p, boost::python::type&>) { - return boost::python::detail::import_extension_class::get_converters()->auto_ptr_from_python(p); - } - - friend PyObject* to_python(std::auto_ptr x) { - return boost::python::detail::import_extension_class::get_converters()->to_python(x); - } - - friend boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) { - return boost::python::detail::import_extension_class::get_converters()->shared_ptr_from_python(p); - } - - friend boost::shared_ptr& from_python(PyObject* p, boost::python::type >) { - return boost::python::detail::import_extension_class::get_converters()->shared_ptr_from_python(p); - } - - friend const boost::shared_ptr& from_python(PyObject* p, boost::python::type&>) { - return boost::python::detail::import_extension_class::get_converters()->shared_ptr_from_python(p); - } - - friend PyObject* to_python(boost::shared_ptr x) { - return boost::python::detail::import_extension_class::get_converters()->to_python(x); - } -}; - -BOOST_PYTHON_END_CONVERSION_NAMESPACE - -namespace boost { namespace python { - -BOOST_PYTHON_IMPORT_CONVERSION(python_import_extension_class_converters); - -// A pointer to this class is exported/imported via the Python API. -// All functions are virtual. This is, what we really export/import -// is essentially just a pointer to a vtbl. -template -struct export_converters_base -{ - virtual const int get_api_major() const { - return detail::EXPORT_CONVERTERS_API_MAJOR; } - virtual const int get_api_minor() const { - return detail::EXPORT_CONVERTERS_API_MINOR; } - virtual PyObject *to_python(const T& x) = 0; - virtual PyObject *to_python(std::auto_ptr x) = 0; - virtual PyObject *to_python(boost::shared_ptr x) = 0; - virtual T* Tptr_from_python(PyObject* obj) = 0; - virtual std::auto_ptr& auto_ptr_from_python(PyObject *obj) = 0; - virtual boost::shared_ptr& shared_ptr_from_python(PyObject *obj) = 0; -}; - -// Converters to be used if T is not copyable. -template -struct export_ptr_converters : export_converters_base -{ - virtual PyObject *to_python(const T& x) { - PyErr_SetString(PyExc_RuntimeError, - "to_python(const T&) converter not exported"); - throw import_error(); - } - virtual PyObject *to_python(std::auto_ptr x) { - return BOOST_PYTHON_CONVERSION::to_python(x); - } - virtual PyObject *to_python(boost::shared_ptr x) { - return BOOST_PYTHON_CONVERSION::to_python(x); - } - virtual T* Tptr_from_python(PyObject* obj) { - return BOOST_PYTHON_CONVERSION::from_python(obj, boost::python::type()); - } - virtual std::auto_ptr& auto_ptr_from_python(PyObject *obj) { - return BOOST_PYTHON_CONVERSION::python_extension_class_converters::ptr_from_python(obj, boost::python::type >()); - } - virtual boost::shared_ptr& shared_ptr_from_python(PyObject *obj) { - return BOOST_PYTHON_CONVERSION::python_extension_class_converters::ptr_from_python(obj, boost::python::type >()); - } -}; - -// The addditional to_python() converter that can be used if T is copyable. -template -struct export_converters : export_ptr_converters -{ - virtual PyObject *to_python(const T& x) { - BOOST_PYTHON_CONVERSION::python_extension_class_converters cv; - return cv.to_python(x); - } -}; - -namespace detail { - -//QUESTIONMARK -// A stripped-down, modified version of class extension_class. -// Would it make sense to establish a formal relationship -// between the two classes? -template -class import_extension_class - : public python_import_extension_class_converters -{ - public: - inline import_extension_class(const char *module, const char* klass) { - m_module = module; - m_klass = klass; - } - - static boost::python::export_converters_base* get_converters(); - - private: - static std::string m_module; - static std::string m_klass; - static boost::python::export_converters_base* imported_converters; -}; - -template std::string import_extension_class::m_module; -template std::string import_extension_class::m_klass; -template -boost::python::export_converters_base* -import_extension_class::imported_converters = 0; - -#ifdef SPECIAL_PYCVTSOBJECT - -// A special PyObject for passing pointers to export_converters_base -template -struct PyCvtsObject { - PyObject_HEAD - export_converters_base* cvts; -}; - -template -void DEL_PyCvtsObject(PyCvtsObject* self) { PyMem_DEL(self); } - -template -PyObject *create_PyCvtsObject(export_converters_base* cvts) -{ - static char PyCvtsObject_Type__doc__[] = - "Boost Python Library (BPL) converters objects to be exported from\n" - "one extension module to another."; - - static PyTypeObject PyCvtsObject_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, /*ob_size*/ - "PyCvtsObject", /*tp_name*/ - sizeof(PyCvtsObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)(static_cast*)> - (DEL_PyCvtsObject)), /*tp_dealloc*/ - (printfunc)0, /*tp_print*/ - (getattrfunc)0, /*tp_getattr*/ - (setattrfunc)0, /*tp_setattr*/ - (cmpfunc)0, /*tp_compare*/ - (reprfunc)0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - (hashfunc)0, /*tp_hash*/ - (ternaryfunc)0, /*tp_call*/ - (reprfunc)0, /*tp_str*/ - - /* Space for future expansion */ - 0L,0L,0L,0L, - PyCvtsObject_Type__doc__ /* Documentation string */ - }; - - PyCvtsObject* self = PyObject_NEW(PyCvtsObject, &PyCvtsObject_Type); - if (self == 0) throw export_error(); - self->cvts = cvts; - return reinterpret_cast(self); -} - -#endif // SPECIAL_PYCVTSOBJECT - -template -boost::python::export_converters_base* -import_extension_class::get_converters() { - if (imported_converters == 0) { -#ifndef SPECIAL_PYCVTSOBJECT - void *cobject - = import_converters(m_module, m_klass, converters_attribute_name); - imported_converters - = static_cast*>(cobject); -#else - ref cvts_obj( - new_import_converters(m_module, m_klass, converters_attribute_name)); - PyCvtsObject* cvts = reinterpret_cast*>(cvts_obj.get()); - imported_converters = cvts->cvts; -#endif - check_export_converters_api( - EXPORT_CONVERTERS_API_MAJOR, - EXPORT_CONVERTERS_API_MINOR, - imported_converters->get_api_major(), - imported_converters->get_api_minor()); - } - return imported_converters; -} - -}}} // namespace boost::python::detail - -namespace boost { namespace python { - -//QUESTIONMARK -// A stripped-down, modified version of class class_builder. -// Would it make sense to establish a formal relationship -// between the two classes? -template -class import_class_builder - : python_import_extension_class_converters -{ - public: - import_class_builder(const char *module, const char* klass) - : m_class(new detail::import_extension_class(module, klass)) - { } - private: - - //QUESTIONMARK - //reference > m_class; - boost::shared_ptr > m_class; -}; - -}} // namespace boost::python - -namespace boost { namespace python { - -// A class_builder that exports the converter functions. -template , - class C = export_converters > -class x_class_builder - : public class_builder -{ - private: - static C export_cvts; - - public: - x_class_builder(module_builder& module, const char* name) - : class_builder(module, name) { -#ifndef SPECIAL_PYCVTSOBJECT - add( - ref(PyCObject_FromVoidPtr(reinterpret_cast(&export_cvts), NULL)), - const_cast(detail::converters_attribute_name.c_str())); -#else - add(ref(detail::create_PyCvtsObject(&export_cvts)), - const_cast(detail::converters_attribute_name.c_str())); -#endif - } -}; - -template -C x_class_builder::export_cvts; - -//QUESTIONMARK -// Is there a better way of making it easy for the end-user -// to choose between x_class_builder and xptr_class_builder? -template , - class C = export_ptr_converters > -class xptr_class_builder : public x_class_builder -{ - public: - xptr_class_builder(module_builder& module, const char* name) - : x_class_builder(module, name) { } -}; - -}} // namespace boost::python - -#endif // X_CLASS_BUILDER_HPP