Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds support for Py_LIMITED_API #14

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 40 additions & 20 deletions pybindgen/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,8 @@ def generate_forward_declarations(self, code_sink, module):
''' % (self.pystruct, self.full_name, self.iter_pystruct))

code_sink.writeln()
code_sink.writeln('extern PyTypeObject %s;' % (self.pytypestruct,))
code_sink.writeln('extern PyTypeObject %s;' % (self.iter_pytypestruct,))
code_sink.writeln('extern PyTypeObject _TYPEDEC %s;' % (self.pytypestruct,))
code_sink.writeln('extern PyTypeObject _TYPEDEC %s;' % (self.iter_pytypestruct,))
code_sink.writeln()

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

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

module.after_init.write_error_check('PyType_Ready(&%s)' % (self.pytypestruct,))
module.after_init.write_error_check('PyType_Ready(&%s)' % (self.iter_pytypestruct,))
module.after_init.write_code('#ifdef Py_LIMITED_API\n'
'%s = (PyTypeObject*)PyType_FromSpec(&%s_spec);\n'
'%s = (PyTypeObject*)PyType_FromSpec(&%s_spec);\n'
'#endif' % (self.pytypestruct, self.pytypestruct,
self.iter_pytypestruct, self.iter_pytypestruct))

module.after_init.write_error_check('PyType_Ready(_TYPEREF %s)' % (self.pytypestruct,))
module.after_init.write_error_check('PyType_Ready(_TYPEREF %s)' % (self.iter_pytypestruct,))

class_python_name = self.python_name

if self.outer_class is None:
module.after_init.write_code(
'PyModule_AddObject(m, (char *) \"%s\", (PyObject *) &%s);' % (
'PyModule_AddObject(m, (char *) \"%s\", (PyObject *) _TYPEREF %s);' % (
class_python_name, self.pytypestruct))
module.after_init.write_code(
'PyModule_AddObject(m, (char *) \"%s\", (PyObject *) &%s);' % (
'PyModule_AddObject(m, (char *) \"%s\", (PyObject *) _TYPEREF %s);' % (
class_python_name+'Iter', self.iter_pytypestruct))
else:
module.after_init.write_code(
Expand Down Expand Up @@ -438,10 +445,13 @@ def _generate_destructor(self, code_sink):
%s(%s *self)
{
%s
#ifdef Py_LIMITED_API
PyObject_DEL(self);
#else
Py_TYPE(self)->tp_free((PyObject*)self);
#endif
}
''' % (container_tp_dealloc_function_name, self.pystruct,
self._get_container_delete_code()))
''' % (container_tp_dealloc_function_name, self.pystruct, self._get_container_delete_code()))

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

Expand All @@ -454,7 +464,11 @@ def _generate_destructor(self, code_sink):
{
Py_CLEAR(self->container);
%s
#ifdef Py_LIMITED_API
PyObject_DEL(self);
#else
Py_TYPE(self)->tp_free((PyObject*)self);
#endif
}
''' % (iter_tp_dealloc_function_name, self.iter_pystruct, self._get_iter_delete_code()))

Expand All @@ -478,7 +492,7 @@ def _generate_iter_methods(self, code_sink):
static PyObject*
%(CONTAINER_ITER_FUNC)s(%(PYSTRUCT)s *self)
{
%(ITER_PYSTRUCT)s *iter = PyObject_GC_New(%(ITER_PYSTRUCT)s, &%(ITER_PYTYPESTRUCT)s);
%(ITER_PYSTRUCT)s *iter = PyObject_GC_New(%(ITER_PYSTRUCT)s, _TYPEREF %(ITER_PYTYPESTRUCT)s);
Py_INCREF(self);
iter->container = self;
iter->iterator = new %(CTYPE)s::iterator(self->obj->begin());
Expand Down Expand Up @@ -535,14 +549,17 @@ def _generate_container_constructor(self, code_sink):
code_sink.writeln(r'''
int %(CONTAINER_CONVERTER_FUNC_NAME)s(PyObject *arg, %(CTYPE)s *container)
{
#ifndef Py_LIMITED_API
if (PyObject_IsInstance(arg, (PyObject*) &%(PYTYPESTRUCT)s)) {
*container = *((%(PYSTRUCT)s*)arg)->obj;
} else if (PyList_Check(arg)) {
} else
#endif
if (PyList_Check(arg)) {
container->clear();
Py_ssize_t size = PyList_Size(arg);
for (Py_ssize_t i = 0; i < size; i++) {
%(ITEM_CTYPE)s item;
if (!%(ITEM_CONVERTER)s(PyList_GET_ITEM(arg, i), &item)) {
if (!%(ITEM_CONVERTER)s(PyList_GetItem(arg, i), &item)) {
return 0;
}
container->%(ADD_VALUE)s(item);
Expand All @@ -567,22 +584,25 @@ def _generate_container_constructor(self, code_sink):
code_sink.writeln(r'''
int %(CONTAINER_CONVERTER_FUNC_NAME)s(PyObject *arg, %(CTYPE)s *container)
{
#ifndef Py_LIMITED_API
if (PyObject_IsInstance(arg, (PyObject*) &%(PYTYPESTRUCT)s)) {
*container = *((%(PYSTRUCT)s*)arg)->obj;
} else if (PyList_Check(arg)) {
} else
#endif
if (PyList_Check(arg)) {
container->clear();
Py_ssize_t size = PyList_Size(arg);
for (Py_ssize_t i = 0; i < size; i++) {
PyObject *tup = PyList_GET_ITEM(arg, i);
PyObject *tup = PyList_GetItem(arg, i);
if (!PyTuple_Check(tup) || PyTuple_Size(tup) != 2) {
PyErr_SetString(PyExc_TypeError, "items must be tuples with two elements");
return 0;
}
std::pair< %(KEY_CTYPE)s, %(ITEM_CTYPE)s > item;
if (!%(KEY_CONVERTER)s(PyTuple_GET_ITEM(tup, 0), &item.first)) {
if (!%(KEY_CONVERTER)s(PyTuple_GetItem(tup, 0), &item.first)) {
return 0;
}
if (!%(ITEM_CONVERTER)s(PyTuple_GET_ITEM(tup, 1), &item.second)) {
if (!%(ITEM_CONVERTER)s(PyTuple_GetItem(tup, 1), &item.second)) {
return 0;
}
container->%(ADD_VALUE)s(item);
Expand Down Expand Up @@ -693,7 +713,7 @@ def convert_c_to_python(self, wrapper):
self.container_type.pystruct+'*', 'py_'+self.container_type.name)
wrapper.before_call.write_code(
"%s = PyObject_New(%s, %s);" %
(self.py_name, self.container_type.pystruct, '&'+self.container_type.pytypestruct))
(self.py_name, self.container_type.pystruct, '_TYPEREF '+self.container_type.pytypestruct))

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

Expand Down Expand Up @@ -728,7 +748,7 @@ def convert_python_to_c(self, wrapper):
self.container_type.pystruct+'*', 'py_'+self.container_type.name)
wrapper.after_call.write_code(
"%s = PyObject_New(%s, %s);" %
(py_name, self.container_type.pystruct, '&'+self.container_type.pytypestruct))
(py_name, self.container_type.pystruct, '_TYPEREF '+self.container_type.pytypestruct))
wrapper.after_call.write_code("%s->obj = new %s(%s);" % (py_name, self.container_type.full_name, container_tmp_var))
wrapper.build_params.add_parameter("N", [py_name])

Expand All @@ -740,7 +760,7 @@ def convert_c_to_python(self, wrapper):
self.container_type.pystruct+'*', 'py_'+self.container_type.name)
wrapper.before_call.write_code(
"%s = PyObject_New(%s, %s);" %
(self.py_name, self.container_type.pystruct, '&'+self.container_type.pytypestruct))
(self.py_name, self.container_type.pystruct, '_TYPEREF '+self.container_type.pytypestruct))

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

wrapper.after_call.write_code(
"%s = PyObject_New(%s, %s);" %
(py_name, self.container_type.pystruct, '&'+self.container_type.pytypestruct))
(py_name, self.container_type.pystruct, '_TYPEREF '+self.container_type.pytypestruct))

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

Expand Down Expand Up @@ -855,7 +875,7 @@ def convert_c_to_python(self, wrapper):

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

Expand Down
Loading