From dcf7e7cf0c0caac38ebe4da5ca7f13622a95ebe9 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 9 Sep 2002 02:00:53 +0000 Subject: [PATCH] Added support for enums [SVN r15222] --- Jamfile | 1 + include/boost/python/enum.hpp | 75 +++++++++++++++++++++++++++++++++++ include/boost/python/str.hpp | 2 + src/object/class.cpp | 66 +++++++++++++++--------------- src/str.cpp | 4 ++ test/Jamfile | 1 + 6 files changed, 117 insertions(+), 32 deletions(-) create mode 100644 include/boost/python/enum.hpp diff --git a/Jamfile b/Jamfile index d4f30be5..4ff03b82 100644 --- a/Jamfile +++ b/Jamfile @@ -23,6 +23,7 @@ dll bpl src/converter/from_python.cpp src/converter/registry.cpp src/converter/type_id.cpp + src/object/enum.cpp src/object/class.cpp src/object/function.cpp src/object/inheritance.cpp diff --git a/include/boost/python/enum.hpp b/include/boost/python/enum.hpp new file mode 100644 index 00000000..b1ad0d9d --- /dev/null +++ b/include/boost/python/enum.hpp @@ -0,0 +1,75 @@ +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef ENUM_DWA200298_HPP +# define ENUM_DWA200298_HPP + +# include +# include + +namespace boost { namespace python { + +template +struct enum_ : public objects::enum_base +{ + enum_(char const* name); + inline enum_& value(char const* name, T); + + private: + static PyObject* to_python(void const* x); + static void* convertible(PyObject* obj); + static void construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data); +}; + +template +inline enum_::enum_(char const* name) + : enum_base( + name + , &enum_::to_python + , &enum_::convertible + , &enum_::construct + , type_id()) +{ +} + +// This is the conversion function that gets registered for converting +template +PyObject* enum_::to_python(void const* x) +{ + return enum_base::to_python( + converter::registered::converters.class_object + , static_cast(*(T const*)x)); +} + +template +void* enum_::convertible(PyObject* obj) +{ + return PyObject_IsInstance( + obj + , upcast( + converter::registered::converters.class_object)) + + ? obj : 0; +} + +template +void enum_::construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data) +{ + T x = static_cast(PyInt_AS_LONG(obj)); + void* const storage = ((converter::rvalue_from_python_storage*)data)->storage.bytes; + new (storage) T(x); + data->convertible = storage; +} + +template +inline enum_& enum_::value(char const* name, T x) +{ + objects::enum_base::add_value(name, static_cast(x)); + return *this; +} + +}} // namespace boost::python + +#endif // ENUM_DWA200298_HPP diff --git a/include/boost/python/str.hpp b/include/boost/python/str.hpp index ad2689e9..fb8bfe58 100644 --- a/include/boost/python/str.hpp +++ b/include/boost/python/str.hpp @@ -18,6 +18,8 @@ namespace boost { namespace python { class str : public object { public: + BOOST_PYTHON_DECL str(); // new str + BOOST_PYTHON_DECL str(const char* s); // new str explicit BOOST_PYTHON_DECL str(object_cref other); diff --git a/src/object/class.cpp b/src/object/class.cpp index 8af51fc8..3cd62a37 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -192,16 +193,16 @@ namespace objects } -static PyGetSetDef instance_getsets[] = { - {"__dict__", instance_get_dict, instance_set_dict, NULL}, - {0} -}; + static PyGetSetDef instance_getsets[] = { + {"__dict__", instance_get_dict, instance_set_dict, NULL}, + {0} + }; -static PyMemberDef instance_members[] = { - {"__weakref__", T_OBJECT, offsetof(instance<>, weakrefs), 0}, - {0} -}; + static PyMemberDef instance_members[] = { + {"__weakref__", T_OBJECT, offsetof(instance<>, weakrefs), 0}, + {0} + }; static PyTypeObject class_type_object = { PyObject_HEAD_INIT(0) //&class_metatype_object) @@ -275,6 +276,20 @@ static PyMemberDef instance_members[] = { return 0; } + object module_prefix() + { + object result( + PyObject_IsInstance(scope().ptr(), upcast(&PyModule_Type)) + ? object(scope().attr("__name__")) + : api::getattr(scope(), "__module__", str()) + ); + + if (result) + result += '.'; + + return result; + } + namespace { // Find a registered class object corresponding to id. Return a @@ -303,21 +318,17 @@ static PyMemberDef instance_members[] = { } return result; } - } - // class_base constructor - // - // name - the name of the new Python class - // - // num_types - one more than the number of declared bases - // - // types - array of python::type_info, the first item - // corresponding to the class being created, and the - // rest corresponding to its declared bases. - // - - namespace - { + // class_base constructor + // + // name - the name of the new Python class + // + // num_types - one more than the number of declared bases + // + // types - array of python::type_info, the first item + // corresponding to the class being created, and the + // rest corresponding to its declared bases. + // inline object new_class(char const* name, std::size_t num_types, class_id const* const types) { @@ -336,17 +347,8 @@ static PyMemberDef instance_members[] = { PyTuple_SET_ITEM(bases.get(), i - 1, upcast(c.release())); } - object module_name( - PyObject_IsInstance(scope().ptr(), upcast(&PyModule_Type)) - ? object(scope().attr("__name__")) - : api::getattr(scope(), "__module__", object("")) - ); - - if (module_name) - module_name += '.'; - // Call the class metatype to create a new class - object result = object(class_metatype())(module_name + name, bases, dict()); + object result = object(class_metatype())(module_prefix() + name, bases, dict()); assert(PyType_IsSubtype(result.ptr()->ob_type, &PyType_Type)); if (scope().ptr() != Py_None) diff --git a/src/str.cpp b/src/str.cpp index 12031548..f36de233 100644 --- a/src/str.cpp +++ b/src/str.cpp @@ -10,6 +10,10 @@ BOOST_PYTHON_DECL detail::new_reference str::call(object const& arg_) arg_.ptr()); } +BOOST_PYTHON_DECL str::str() + : object(detail::new_reference(PyString_FromString(""))) +{} + BOOST_PYTHON_DECL str::str(const char* s) : object(detail::new_reference(PyString_FromString(s))) {} diff --git a/test/Jamfile b/test/Jamfile index 7dcd3351..511408e8 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -54,6 +54,7 @@ rule bpl-test ( name ? : files * ) boost-python-runtest $(name) : $(py) $(modules) ; } +bpl-test enum ; bpl-test minimal ; bpl-test docstring ; bpl-test exception_translator ;