Skip to content

Commit e04a6e2

Browse files
committed
Move away from static types.
1 parent ff17809 commit e04a6e2

File tree

2 files changed

+92
-69
lines changed

2 files changed

+92
-69
lines changed

src/object/class.cpp

+71-52
Original file line numberDiff line numberDiff line change
@@ -141,16 +141,20 @@ extern "C"
141141
}
142142
}
143143

144-
static PyTypeObject static_data_object = {
145-
PyVarObject_HEAD_INIT(NULL, 0)
146-
.tp_name = const_cast<char*>("Boost.Python.StaticProperty"),
147-
.tp_basicsize = sizeof(propertyobject),
148-
.tp_flags = Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
149-
| Py_TPFLAGS_BASETYPE, /* tp_flags */
150-
.tp_descr_get = static_data_descr_get,
151-
.tp_descr_set = static_data_descr_set,
152-
.tp_init = property_init,
144+
static PyType_Slot static_data_object_slots[] = {
145+
{Py_tp_descr_get, (void*)static_data_descr_get},
146+
{Py_tp_descr_set, (void*)static_data_descr_set},
147+
{Py_tp_init, (void*)property_init},
153148
};
149+
static PyType_Spec static_data_object_spec = {
150+
const_cast<char*>("Boost.Python.StaticProperty"),
151+
sizeof(propertyobject),
152+
0,
153+
Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
154+
| Py_TPFLAGS_BASETYPE,
155+
static_data_object_slots,
156+
};
157+
154158

155159
namespace objects
156160
{
@@ -165,14 +169,16 @@ namespace objects
165169

166170
BOOST_PYTHON_DECL PyObject* static_data()
167171
{
168-
if (static_data_object.tp_dict == 0)
172+
173+
PyTypeObject* not_static_data_object = (PyTypeObject*)PyType_FromSpec(&static_data_object_spec);
174+
if (not_static_data_object->tp_dict == 0)
169175
{
170-
Py_TYPE(&static_data_object) = &PyType_Type;
171-
static_data_object.tp_base = &PyProperty_Type;
172-
if (PyType_Ready(&static_data_object))
176+
Py_TYPE(not_static_data_object) = &PyType_Type;
177+
not_static_data_object->tp_base = &PyProperty_Type;
178+
if (PyType_Ready(not_static_data_object))
173179
return 0;
174180
}
175-
return upcast<PyObject>(&static_data_object);
181+
return upcast<PyObject>(not_static_data_object);
176182
}
177183
}
178184

@@ -206,21 +212,26 @@ extern "C"
206212
}
207213
}
208214

209-
static PyTypeObject class_metatype_object = {
210-
PyVarObject_HEAD_INIT(NULL, 0)
211-
.tp_name = const_cast<char*>("Boost.Python.class"),
212-
.tp_basicsize = PyType_Type.tp_basicsize,
213-
.tp_setattro = class_setattro,
214-
.tp_flags = Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
215-
| Py_TPFLAGS_BASETYPE, /* tp_flags */
216-
.tp_is_gc = (inquiry)type_is_gc,
215+
static PyType_Slot class_metatype_object_slots[] = {
216+
{Py_tp_setattro, (void*)class_setattro},
217+
{Py_tp_is_gc, (void*)type_is_gc},
218+
};
219+
static PyType_Spec class_metatype_object_spec = {
220+
const_cast<char*>("Boost.Python.class"),
221+
PyType_Type.tp_basicsize,
222+
0,
223+
Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
224+
| Py_TPFLAGS_BASETYPE,
225+
class_metatype_object_slots,
217226
};
218227

228+
219229
// Install the instance data for a C++ object into a Python instance
220230
// object.
221231
void instance_holder::install(PyObject* self) throw()
222232
{
223-
assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self)), &class_metatype_object));
233+
PyTypeObject* class_metatype_object = (PyTypeObject*)PyType_FromSpec(&class_metatype_object_spec);
234+
assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self)), class_metatype_object));
224235
m_next = ((objects::instance<>*)self)->objects;
225236
((objects::instance<>*)self)->objects = this;
226237
}
@@ -231,14 +242,15 @@ namespace objects
231242
// Get the metatype object for all extension classes.
232243
BOOST_PYTHON_DECL type_handle class_metatype()
233244
{
234-
if (class_metatype_object.tp_dict == 0)
245+
PyTypeObject* class_metatype_object = (PyTypeObject*)PyType_FromSpec(&class_metatype_object_spec);
246+
if (class_metatype_object->tp_dict == 0)
235247
{
236-
Py_TYPE(&class_metatype_object) = &PyType_Type;
237-
class_metatype_object.tp_base = &PyType_Type;
238-
if (PyType_Ready(&class_metatype_object))
248+
Py_TYPE(class_metatype_object) = &PyType_Type;
249+
class_metatype_object->tp_base = &PyType_Type;
250+
if (PyType_Ready(class_metatype_object))
239251
return type_handle();
240252
}
241-
return type_handle(borrowed(&class_metatype_object));
253+
return type_handle(borrowed(class_metatype_object));
242254
}
243255
extern "C"
244256
{
@@ -331,40 +343,45 @@ namespace objects
331343
{0, 0, 0, 0, 0}
332344
};
333345

334-
static PyTypeObject class_type_object = {
335-
PyVarObject_HEAD_INIT(NULL, 0)
336-
.tp_name = const_cast<char*>("Boost.Python.instance"),
337-
.tp_basicsize =offsetof(instance<>,storage),
338-
.tp_itemsize = 1,
339-
.tp_dealloc = instance_dealloc,
340-
.tp_flags = Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
341-
| Py_TPFLAGS_BASETYPE, /* tp_flags */
342-
.tp_weaklistoffset =offsetof(instance<>,weakrefs),
343-
.tp_members = instance_members,
344-
.tp_getset = instance_getsets,
345-
.tp_dictoffset = offsetof(instance<>,dict),
346-
.tp_alloc = PyType_GenericAlloc,
347-
.tp_new = instance_new,
346+
static PyType_Slot class_type_object_slots[] = {
347+
{Py_tp_dealloc, (void*)instance_dealloc},
348+
{Py_tp_members, instance_members},
349+
{Py_tp_getset, instance_getsets},
350+
{Py_tp_alloc, (void*)PyType_GenericAlloc},
351+
{Py_tp_new, (void*)instance_new},
352+
};
353+
static PyType_Spec class_type_object_spec = {
354+
const_cast<char*>("Boost.Python.instance"),
355+
offsetof(instance<>,storage),
356+
1,
357+
Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
358+
| Py_TPFLAGS_BASETYPE,
359+
class_type_object_slots,
348360
};
349361

362+
350363
BOOST_PYTHON_DECL type_handle class_type()
351364
{
352-
if (class_type_object.tp_dict == 0)
365+
PyTypeObject* class_type_object = (PyTypeObject*)PyType_FromSpec(&class_type_object_spec);
366+
class_type_object->tp_weaklistoffset = offsetof(instance<>,weakrefs);
367+
class_type_object->tp_dictoffset = offsetof(instance<>,dict);
368+
if (class_type_object->tp_dict == 0)
353369
{
354370
Py_TYPE(&class_type_object) = incref(class_metatype().get());
355-
class_type_object.tp_base = &PyBaseObject_Type;
356-
if (PyType_Ready(&class_type_object))
371+
class_type_object->tp_base = &PyBaseObject_Type;
372+
if (PyType_Ready(class_type_object))
357373
return type_handle();
358-
// class_type_object.tp_setattro = class_setattro;
374+
// class_type_object->tp_setattro = class_setattro;
359375
}
360-
return type_handle(borrowed(&class_type_object));
376+
return type_handle(borrowed(class_type_object));
361377
}
362378

363379
BOOST_PYTHON_DECL void*
364380
find_instance_impl(PyObject* inst, type_info type, bool null_shared_ptr_only)
365381
{
382+
PyTypeObject* class_metatype_object = (PyTypeObject*)PyType_FromSpec(&class_metatype_object_spec);
366383
if (!Py_TYPE(Py_TYPE(inst)) ||
367-
!PyType_IsSubtype(Py_TYPE(Py_TYPE(inst)), &class_metatype_object))
384+
!PyType_IsSubtype(Py_TYPE(Py_TYPE(inst)), class_metatype_object))
368385
return 0;
369386

370387
instance<>* self = reinterpret_cast<instance<>*>(inst);
@@ -440,8 +457,8 @@ namespace objects
440457
for (ssize_t i = 1; i <= num_bases; ++i)
441458
{
442459
type_handle c = (i >= static_cast<ssize_t>(num_types)) ? class_type() : get_class(types[i]);
443-
// PyTuple_SetItem steals this reference
444-
PyTuple_SetItem(bases.get(), static_cast<ssize_t>(i - 1), upcast<PyObject>(c.release()));
460+
// PyTuple_SET_ITEM steals this reference
461+
PyTuple_SET_ITEM(bases.get(), static_cast<ssize_t>(i - 1), upcast<PyObject>(c.release()));
445462
}
446463

447464
// Call the class metatype to create a new class
@@ -609,7 +626,8 @@ namespace objects
609626

610627
void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size)
611628
{
612-
assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)), &class_metatype_object));
629+
assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)),
630+
(PyTypeObject*)PyType_FromSpec(&class_metatype_object_spec)));
613631
objects::instance<>* self = (objects::instance<>*)self_;
614632

615633
int total_size_needed = holder_offset + holder_size;
@@ -634,7 +652,8 @@ void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std:
634652

635653
void instance_holder::deallocate(PyObject* self_, void* storage) throw()
636654
{
637-
assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)), &class_metatype_object));
655+
assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)),
656+
(PyTypeObject*)PyType_FromSpec(&class_metatype_object_spec)));
638657
objects::instance<>* self = (objects::instance<>*)self_;
639658
if (storage != (char*)self + Py_SIZE(self))
640659
{

src/object/enum.cpp

+21-17
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ extern "C"
5252
#if PY_VERSION_HEX >= 0x03000000
5353
PyUnicode_FromFormat("%S.%s(%ld)", mod, self_->ob_type->tp_name, PyLong_AsLong(self_));
5454
#else
55-
PyString_FromFormat("%s.%s(%ld)", PyString_AsString(mod), self_->ob_type->tp_name, PyInt_AsLong(self_));
55+
PyString_FromFormat("%s.%s(%ld)", PyString_AsString(mod), self_->ob_type->tp_name, PyInt_AS_LONG(self_));
5656
#endif
5757
}
5858
else
@@ -89,43 +89,47 @@ extern "C"
8989
}
9090
}
9191

92-
static PyTypeObject enum_type_object = {
93-
PyVarObject_HEAD_INIT(NULL, 0) // &PyType_Type
94-
.tp_name = const_cast<char*>("Boost.Python.enum"),
95-
.tp_basicsize = sizeof(enum_object),
96-
.tp_dealloc = (destructor) enum_dealloc,
97-
.tp_repr = enum_repr,
98-
.tp_str = enum_str,
99-
.tp_flags =
92+
static PyType_Slot enum_type_object_slots[] = {
93+
{Py_tp_dealloc, (void*) enum_dealloc},
94+
{Py_tp_repr, (void*) enum_repr},
95+
{Py_tp_str, (void*) enum_str},
96+
{Py_tp_members, (void*) enum_members},
97+
};
98+
static PyType_Spec enum_type_object_spec = {
99+
const_cast<char*>("Boost.Python.enum"),
100+
sizeof(enum_object),
101+
0,
100102
Py_TPFLAGS_DEFAULT
101103
#if PY_VERSION_HEX < 0x03000000
102104
| Py_TPFLAGS_CHECKTYPES
103105
#endif
104106
| Py_TPFLAGS_HAVE_GC
105-
| Py_TPFLAGS_BASETYPE, /* tp_flags */
106-
.tp_members = enum_members,
107+
| Py_TPFLAGS_BASETYPE,
108+
enum_type_object_slots,
107109
};
108110

111+
109112
object module_prefix();
110113

111114
namespace
112115
{
113116
object new_enum_type(char const* name, char const *doc)
114117
{
115-
if (enum_type_object.tp_dict == 0)
118+
PyTypeObject* enum_type_object = (PyTypeObject*)PyType_FromSpec(&enum_type_object_spec);
119+
if (enum_type_object->tp_dict == 0)
116120
{
117-
Py_TYPE(&enum_type_object) = incref(&PyType_Type);
121+
Py_TYPE(enum_type_object) = incref(&PyType_Type);
118122
#if PY_VERSION_HEX >= 0x03000000
119-
enum_type_object.tp_base = &PyLong_Type;
123+
enum_type_object->tp_base = &PyLong_Type;
120124
#else
121-
enum_type_object.tp_base = &PyInt_Type;
125+
enum_type_object->tp_base = &PyInt_Type;
122126
#endif
123-
if (PyType_Ready(&enum_type_object))
127+
if (PyType_Ready(enum_type_object))
124128
throw_error_already_set();
125129
}
126130

127131
type_handle metatype(borrowed(&PyType_Type));
128-
type_handle base(borrowed(&enum_type_object));
132+
type_handle base(borrowed(enum_type_object));
129133

130134
// suppress the instance __dict__ in these enum objects. There
131135
// may be a slicker way, but this'll do for now.

0 commit comments

Comments
 (0)