Thankyou!!! That was it. Saved me a lot of time debugging no doubt and potential nasty problems at customer sites etc.
I must admit I had just pattern-matched with these functions but had no idea that some of them stole references. I still don't really understand why, the docs say it is a "common idiom", but not common enough to be familiar to me and tricky to be inconsistent. But now I know, and the crash is gone :) Regards and many thanks again, /Geoff On Mon, Oct 7, 2019 at 7:32 PM MRAB <pyt...@mrabarnett.plus.com> wrote: > On 2019-10-07 08:04, Geoff Bache wrote: > > It's possible. Our embedding code is fairly simple and we've tried to > > encapsulate all the DECREFing in resource objects, i.e. that do DECREF > > in their destructor when they go out of scope. We hoped this would > > minimise this sort of problem. > > The C++ calling code essentially tries to call progwrapper.prog with a > > dictionary as arguments, and looks like > > > > GilStateHolder pyStateHolder; > > PyRefHolder module(PyImport_ImportModule("progwrapper")); > > > > if (module._ref) > > { > > PyXRefHolder func(PyObject_GetAttrString(module._ref, "prog")); > > PyXRefHolder pyArgs(PyTuple_New(1)); > > PyXRefHolder pyDict(convertDictForPython(dictIn)); > > PyTuple_SetItem(pyArgs._ref, 0, pyDict._ref); > > |Do you DECREF pyDict._ref later on? I ask because PyTuple_SetItem > steals a reference.| > > |Many other functions that "store" an object, such as PyList_Append, > INCREF to retain the stored object, but PyTuple_SetItem doesn't.| > > || > > > PyRefHolder pyRet(PyObject_CallObject(func._ref, pyArgs._ref)); > > > > if (pyRet._ref != NULL) > > { > > addPythonValuesToDict(pyRet._ref, theDict); > > ... > > > > where GilStateHolder, PyRefHolder etc are such resource objects as > > described above, wrapping round the PyObject pointers etc. > > > > [snip] > > -- > https://mail.python.org/mailman/listinfo/python-list > -- https://mail.python.org/mailman/listinfo/python-list