Skip to content

Commit 074b9b2

Browse files
committed
Adds support for Py_LIMITED_API
1 parent 0466ae3 commit 074b9b2

File tree

7 files changed

+142
-54
lines changed

7 files changed

+142
-54
lines changed

pybindgen/container.py

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,8 @@ def generate_forward_declarations(self, code_sink, module):
308308
''' % (self.pystruct, self.full_name, self.iter_pystruct))
309309

310310
code_sink.writeln()
311-
code_sink.writeln('extern PyTypeObject %s;' % (self.pytypestruct,))
312-
code_sink.writeln('extern PyTypeObject %s;' % (self.iter_pytypestruct,))
311+
code_sink.writeln('extern PyTypeObject _TYPEDEC %s;' % (self.pytypestruct,))
312+
code_sink.writeln('extern PyTypeObject _TYPEDEC %s;' % (self.iter_pytypestruct,))
313313
code_sink.writeln()
314314

315315
this_type_converter = self.module.get_root().get_python_to_c_type_converter_function_name(
@@ -346,18 +346,25 @@ def generate(self, code_sink, module, docstring=None):
346346

347347
## --- register the class type in the module ---
348348
module.after_init.write_code("/* Register the '%s' class */" % self.full_name)
349+
#import traceback; module.after_init.write_code(repr(traceback.format_stack()))
349350

350-
module.after_init.write_error_check('PyType_Ready(&%s)' % (self.pytypestruct,))
351-
module.after_init.write_error_check('PyType_Ready(&%s)' % (self.iter_pytypestruct,))
351+
module.after_init.write_code('#ifdef Py_LIMITED_API\n'
352+
'%s = (PyTypeObject*)PyType_FromSpec(&%s_spec);\n'
353+
'%s = (PyTypeObject*)PyType_FromSpec(&%s_spec);\n'
354+
'#endif' % (self.pytypestruct, self.pytypestruct,
355+
self.iter_pytypestruct, self.iter_pytypestruct))
356+
357+
module.after_init.write_error_check('PyType_Ready(_TYPEREF %s)' % (self.pytypestruct,))
358+
module.after_init.write_error_check('PyType_Ready(_TYPEREF %s)' % (self.iter_pytypestruct,))
352359

353360
class_python_name = self.python_name
354361

355362
if self.outer_class is None:
356363
module.after_init.write_code(
357-
'PyModule_AddObject(m, (char *) \"%s\", (PyObject *) &%s);' % (
364+
'PyModule_AddObject(m, (char *) \"%s\", (PyObject *) _TYPEREF %s);' % (
358365
class_python_name, self.pytypestruct))
359366
module.after_init.write_code(
360-
'PyModule_AddObject(m, (char *) \"%s\", (PyObject *) &%s);' % (
367+
'PyModule_AddObject(m, (char *) \"%s\", (PyObject *) _TYPEREF %s);' % (
361368
class_python_name+'Iter', self.iter_pytypestruct))
362369
else:
363370
module.after_init.write_code(
@@ -438,10 +445,13 @@ def _generate_destructor(self, code_sink):
438445
%s(%s *self)
439446
{
440447
%s
448+
#ifdef Py_LIMITED_API
449+
PyObject_DEL(self);
450+
#else
441451
Py_TYPE(self)->tp_free((PyObject*)self);
452+
#endif
442453
}
443-
''' % (container_tp_dealloc_function_name, self.pystruct,
444-
self._get_container_delete_code()))
454+
''' % (container_tp_dealloc_function_name, self.pystruct, self._get_container_delete_code()))
445455

446456
self.pytype.slots.setdefault("tp_dealloc", container_tp_dealloc_function_name )
447457

@@ -454,7 +464,11 @@ def _generate_destructor(self, code_sink):
454464
{
455465
Py_CLEAR(self->container);
456466
%s
467+
#ifdef Py_LIMITED_API
468+
PyObject_DEL(self);
469+
#else
457470
Py_TYPE(self)->tp_free((PyObject*)self);
471+
#endif
458472
}
459473
''' % (iter_tp_dealloc_function_name, self.iter_pystruct, self._get_iter_delete_code()))
460474

@@ -478,7 +492,7 @@ def _generate_iter_methods(self, code_sink):
478492
static PyObject*
479493
%(CONTAINER_ITER_FUNC)s(%(PYSTRUCT)s *self)
480494
{
481-
%(ITER_PYSTRUCT)s *iter = PyObject_GC_New(%(ITER_PYSTRUCT)s, &%(ITER_PYTYPESTRUCT)s);
495+
%(ITER_PYSTRUCT)s *iter = PyObject_GC_New(%(ITER_PYSTRUCT)s, _TYPEREF %(ITER_PYTYPESTRUCT)s);
482496
Py_INCREF(self);
483497
iter->container = self;
484498
iter->iterator = new %(CTYPE)s::iterator(self->obj->begin());
@@ -542,7 +556,7 @@ def _generate_container_constructor(self, code_sink):
542556
Py_ssize_t size = PyList_Size(arg);
543557
for (Py_ssize_t i = 0; i < size; i++) {
544558
%(ITEM_CTYPE)s item;
545-
if (!%(ITEM_CONVERTER)s(PyList_GET_ITEM(arg, i), &item)) {
559+
if (!%(ITEM_CONVERTER)s(PyList_GetItem(arg, i), &item)) {
546560
return 0;
547561
}
548562
container->%(ADD_VALUE)s(item);
@@ -573,16 +587,16 @@ def _generate_container_constructor(self, code_sink):
573587
container->clear();
574588
Py_ssize_t size = PyList_Size(arg);
575589
for (Py_ssize_t i = 0; i < size; i++) {
576-
PyObject *tup = PyList_GET_ITEM(arg, i);
590+
PyObject *tup = PyList_GetItem(arg, i);
577591
if (!PyTuple_Check(tup) || PyTuple_Size(tup) != 2) {
578592
PyErr_SetString(PyExc_TypeError, "items must be tuples with two elements");
579593
return 0;
580594
}
581595
std::pair< %(KEY_CTYPE)s, %(ITEM_CTYPE)s > item;
582-
if (!%(KEY_CONVERTER)s(PyTuple_GET_ITEM(tup, 0), &item.first)) {
596+
if (!%(KEY_CONVERTER)s(PyTuple_GetItem(tup, 0), &item.first)) {
583597
return 0;
584598
}
585-
if (!%(ITEM_CONVERTER)s(PyTuple_GET_ITEM(tup, 1), &item.second)) {
599+
if (!%(ITEM_CONVERTER)s(PyTuple_GetItem(tup, 1), &item.second)) {
586600
return 0;
587601
}
588602
container->%(ADD_VALUE)s(item);
@@ -693,7 +707,7 @@ def convert_c_to_python(self, wrapper):
693707
self.container_type.pystruct+'*', 'py_'+self.container_type.name)
694708
wrapper.before_call.write_code(
695709
"%s = PyObject_New(%s, %s);" %
696-
(self.py_name, self.container_type.pystruct, '&'+self.container_type.pytypestruct))
710+
(self.py_name, self.container_type.pystruct, '_TYPEREF '+self.container_type.pytypestruct))
697711

698712
wrapper.before_call.write_code("%s->obj = new %s(%s);" % (self.py_name, self.container_type.full_name, self.value))
699713

@@ -728,7 +742,7 @@ def convert_python_to_c(self, wrapper):
728742
self.container_type.pystruct+'*', 'py_'+self.container_type.name)
729743
wrapper.after_call.write_code(
730744
"%s = PyObject_New(%s, %s);" %
731-
(py_name, self.container_type.pystruct, '&'+self.container_type.pytypestruct))
745+
(py_name, self.container_type.pystruct, '_TYPEREF '+self.container_type.pytypestruct))
732746
wrapper.after_call.write_code("%s->obj = new %s(%s);" % (py_name, self.container_type.full_name, container_tmp_var))
733747
wrapper.build_params.add_parameter("N", [py_name])
734748

@@ -740,7 +754,7 @@ def convert_c_to_python(self, wrapper):
740754
self.container_type.pystruct+'*', 'py_'+self.container_type.name)
741755
wrapper.before_call.write_code(
742756
"%s = PyObject_New(%s, %s);" %
743-
(self.py_name, self.container_type.pystruct, '&'+self.container_type.pytypestruct))
757+
(self.py_name, self.container_type.pystruct, '_TYPEREF '+self.container_type.pytypestruct))
744758

745759
if self.direction & Parameter.DIRECTION_IN:
746760
wrapper.before_call.write_code("%s->obj = new %s(%s);" % (self.py_name, self.container_type.full_name, self.name))
@@ -800,7 +814,7 @@ def convert_python_to_c(self, wrapper):
800814

801815
wrapper.after_call.write_code(
802816
"%s = PyObject_New(%s, %s);" %
803-
(py_name, self.container_type.pystruct, '&'+self.container_type.pytypestruct))
817+
(py_name, self.container_type.pystruct, '_TYPEREF '+self.container_type.pytypestruct))
804818

805819
wrapper.after_call.write_code("%s->obj = %s;" % (py_name, container_tmp_var))
806820

@@ -855,7 +869,7 @@ def convert_c_to_python(self, wrapper):
855869

856870
wrapper.after_call.write_code(
857871
"%s = PyObject_New(%s, %s);" %
858-
(py_name, self.container_type.pystruct, '&'+self.container_type.pytypestruct))
872+
(py_name, self.container_type.pystruct, '_TYPEREF '+self.container_type.pytypestruct))
859873
wrapper.after_call.write_code("%s->obj = new %s(%s);" % (self.py_name, self.container_type.full_name, self.value))
860874
wrapper.build_params.add_parameter("N", [py_name], prepend=True)
861875

0 commit comments

Comments
 (0)