I have a wrapper class as in the example below, written in Python.
class Foo:
def __init__(self, bar=None):
if bar:
self._bar = bar
else:
self._bar = CreateBarObject("value")
I create an instance via the Python C API
// c++ pseudo code for convenience
auto obj = PyObject_CallObject(Foo)
auto bar = CreateBarObject("another_value");
PyObject_SetAttrString(obj, "_bar", bar)
As you can see from the code, Foo.__init__
will be called when an instance gets created which creates a new bar
object. But I would like to bypass this "heavy" operation. So any safe way to create an instance of Foo so I can set self._bar
via the Python C API? Any ideas?
You should be able to directly invoke the tp_new
of Foo
(equivalent to invoking Foo.__new__
at the Python layer). That will perform the allocation and C level "mandatory initialization" work, without the "optional initialization" work of tp_init
/__init__
. It's the same strategy pickle
uses to create instances of a type without initializing them (so it can fill them in via __setstate__
or directly filling in __dict__
, as appropriate).
Assuming Foo
is a C level PyTypeObject*
, something like this should do the trick:
auto emptytup = PyTuple_New(0); /* AFAICT, the args tuple is mandatory, but kwargs is optional */
/* Error check for PyTuple_New failure */
auto obj = Foo->tp_new(Foo, emptytup, NULL);
Py_DECREF(emptytup);
/* Error check for new fail */
auto bar = CreateBarObject("another_value");
PyObject_SetAttrString(obj, "_bar", bar)