Skip to content

Commit dcf7e7c

Browse files
committed
Added support for enums
[SVN r15222]
1 parent 4c8bcd9 commit dcf7e7c

File tree

6 files changed

+117
-32
lines changed

6 files changed

+117
-32
lines changed

Jamfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ dll bpl
2323
src/converter/from_python.cpp
2424
src/converter/registry.cpp
2525
src/converter/type_id.cpp
26+
src/object/enum.cpp
2627
src/object/class.cpp
2728
src/object/function.cpp
2829
src/object/inheritance.cpp

include/boost/python/enum.hpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright David Abrahams 2002. Permission to copy, use,
2+
// modify, sell and distribute this software is granted provided this
3+
// copyright notice appears in all copies. This software is provided
4+
// "as is" without express or implied warranty, and with no claim as
5+
// to its suitability for any purpose.
6+
#ifndef ENUM_DWA200298_HPP
7+
# define ENUM_DWA200298_HPP
8+
9+
# include <boost/python/object/enum_base.hpp>
10+
# include <boost/python/converter/rvalue_from_python_data.hpp>
11+
12+
namespace boost { namespace python {
13+
14+
template <class T>
15+
struct enum_ : public objects::enum_base
16+
{
17+
enum_(char const* name);
18+
inline enum_<T>& value(char const* name, T);
19+
20+
private:
21+
static PyObject* to_python(void const* x);
22+
static void* convertible(PyObject* obj);
23+
static void construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data);
24+
};
25+
26+
template <class T>
27+
inline enum_<T>::enum_(char const* name)
28+
: enum_base(
29+
name
30+
, &enum_<T>::to_python
31+
, &enum_<T>::convertible
32+
, &enum_<T>::construct
33+
, type_id<T>())
34+
{
35+
}
36+
37+
// This is the conversion function that gets registered for converting
38+
template <class T>
39+
PyObject* enum_<T>::to_python(void const* x)
40+
{
41+
return enum_base::to_python(
42+
converter::registered<T>::converters.class_object
43+
, static_cast<long>(*(T const*)x));
44+
}
45+
46+
template <class T>
47+
void* enum_<T>::convertible(PyObject* obj)
48+
{
49+
return PyObject_IsInstance(
50+
obj
51+
, upcast<PyObject>(
52+
converter::registered<T>::converters.class_object))
53+
54+
? obj : 0;
55+
}
56+
57+
template <class T>
58+
void enum_<T>::construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data)
59+
{
60+
T x = static_cast<T>(PyInt_AS_LONG(obj));
61+
void* const storage = ((converter::rvalue_from_python_storage<T>*)data)->storage.bytes;
62+
new (storage) T(x);
63+
data->convertible = storage;
64+
}
65+
66+
template <class T>
67+
inline enum_<T>& enum_<T>::value(char const* name, T x)
68+
{
69+
objects::enum_base::add_value(name, static_cast<long>(x));
70+
return *this;
71+
}
72+
73+
}} // namespace boost::python
74+
75+
#endif // ENUM_DWA200298_HPP

include/boost/python/str.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ namespace boost { namespace python {
1818
class str : public object
1919
{
2020
public:
21+
BOOST_PYTHON_DECL str(); // new str
22+
2123
BOOST_PYTHON_DECL str(const char* s); // new str
2224
explicit BOOST_PYTHON_DECL str(object_cref other);
2325

src/object/class.cpp

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <boost/detail/binary_search.hpp>
1717
#include <boost/python/self.hpp>
1818
#include <boost/python/dict.hpp>
19+
#include <boost/python/str.hpp>
1920
#include <boost/bind.hpp>
2021
#include <functional>
2122
#include <vector>
@@ -192,16 +193,16 @@ namespace objects
192193
}
193194

194195

195-
static PyGetSetDef instance_getsets[] = {
196-
{"__dict__", instance_get_dict, instance_set_dict, NULL},
197-
{0}
198-
};
196+
static PyGetSetDef instance_getsets[] = {
197+
{"__dict__", instance_get_dict, instance_set_dict, NULL},
198+
{0}
199+
};
199200

200201

201-
static PyMemberDef instance_members[] = {
202-
{"__weakref__", T_OBJECT, offsetof(instance<>, weakrefs), 0},
203-
{0}
204-
};
202+
static PyMemberDef instance_members[] = {
203+
{"__weakref__", T_OBJECT, offsetof(instance<>, weakrefs), 0},
204+
{0}
205+
};
205206

206207
static PyTypeObject class_type_object = {
207208
PyObject_HEAD_INIT(0) //&class_metatype_object)
@@ -275,6 +276,20 @@ static PyMemberDef instance_members[] = {
275276
return 0;
276277
}
277278

279+
object module_prefix()
280+
{
281+
object result(
282+
PyObject_IsInstance(scope().ptr(), upcast<PyObject>(&PyModule_Type))
283+
? object(scope().attr("__name__"))
284+
: api::getattr(scope(), "__module__", str())
285+
);
286+
287+
if (result)
288+
result += '.';
289+
290+
return result;
291+
}
292+
278293
namespace
279294
{
280295
// Find a registered class object corresponding to id. Return a
@@ -303,21 +318,17 @@ static PyMemberDef instance_members[] = {
303318
}
304319
return result;
305320
}
306-
}
307321

308-
// class_base constructor
309-
//
310-
// name - the name of the new Python class
311-
//
312-
// num_types - one more than the number of declared bases
313-
//
314-
// types - array of python::type_info, the first item
315-
// corresponding to the class being created, and the
316-
// rest corresponding to its declared bases.
317-
//
318-
319-
namespace
320-
{
322+
// class_base constructor
323+
//
324+
// name - the name of the new Python class
325+
//
326+
// num_types - one more than the number of declared bases
327+
//
328+
// types - array of python::type_info, the first item
329+
// corresponding to the class being created, and the
330+
// rest corresponding to its declared bases.
331+
//
321332
inline object
322333
new_class(char const* name, std::size_t num_types, class_id const* const types)
323334
{
@@ -336,17 +347,8 @@ static PyMemberDef instance_members[] = {
336347
PyTuple_SET_ITEM(bases.get(), i - 1, upcast<PyObject>(c.release()));
337348
}
338349

339-
object module_name(
340-
PyObject_IsInstance(scope().ptr(), upcast<PyObject>(&PyModule_Type))
341-
? object(scope().attr("__name__"))
342-
: api::getattr(scope(), "__module__", object(""))
343-
);
344-
345-
if (module_name)
346-
module_name += '.';
347-
348350
// Call the class metatype to create a new class
349-
object result = object(class_metatype())(module_name + name, bases, dict());
351+
object result = object(class_metatype())(module_prefix() + name, bases, dict());
350352
assert(PyType_IsSubtype(result.ptr()->ob_type, &PyType_Type));
351353

352354
if (scope().ptr() != Py_None)

src/str.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ BOOST_PYTHON_DECL detail::new_reference str::call(object const& arg_)
1010
arg_.ptr());
1111
}
1212

13+
BOOST_PYTHON_DECL str::str()
14+
: object(detail::new_reference(PyString_FromString("")))
15+
{}
16+
1317
BOOST_PYTHON_DECL str::str(const char* s)
1418
: object(detail::new_reference(PyString_FromString(s)))
1519
{}

test/Jamfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ rule bpl-test ( name ? : files * )
5454
boost-python-runtest $(name) : $(py) <pyd>$(modules) ;
5555
}
5656

57+
bpl-test enum ;
5758
bpl-test minimal ;
5859
bpl-test docstring ;
5960
bpl-test exception_translator ;

0 commit comments

Comments
 (0)