<p>问题是这个代码:</p>
<pre><code>py_func = PyDict_GetItemString(py_lib_mod_dict, "func2"); //fails here when cfunc1 is called via callback... will not even go to the next line!
printf("Done with GetItemString\n");
py_ret = PyObject_CallFunction(py_func, 0);
Py_DECREF(py_func);
</code></pre>
<p>正如<a href="http://docs.python.org/2/c-api/dict.html#PyDict_GetItemString" rel="noreferrer">the docs</a>所说,<code>PyDict_GetItemString</code>返回一个借用的引用。所以,当你第一次打电话到这里时,你借用了引用,并减少了它,导致它被销毁。下次你打电话的时候,你会收到垃圾,然后试着打电话给它。在</p>
<p>所以,要修复它,只需删除<code>Py_DECREF(py_func)</code>(或在<code>pyfunc =</code>行后添加<code>Py_INCREF(py_func)</code>)。在</p>
<p>实际上,您通常会返回一个特殊的“dead”对象,因此您可以非常容易地测试这个对象:在<code>py_func =</code>行之后和<code>Py_DECREF</code>行后面放一个<code><function func2 at 0x10b9f1230></code>,第二次和第三次可能会看到类似<code><function func2 at 0x10b9f1230></code>,第二次和第三次(你不会看到第四个,因为它会在到达之前崩溃)。在</p>
<p>而{cd16}则可以在{cd16}中运行{cd11>,而不是^ cd16}来修复{cd16}的代码。在</p>
<p>还有…你不应该把GIL放在里面吗?我不常写这样的代码,所以也许我错了。我不会因为代码而崩溃。显然,生成一个线程来运行<code>cfunc1</code><em>会导致</em>崩溃,<code>PyGILState_Ensure</code>/<code>Release</code>解决了这个崩溃……但这并不能证明您在单线程情况下需要任何东西。{你先看看这件事和我的案子没什么关系。在</p>
<p>顺便说一句,如果您是Python扩展和嵌入的新手:大量无法解释的崩溃,就像这次一样,都是由手动引用错误引起的。这就是<code>boost::python</code>等事物存在的原因。这并不是说用纯C API是不可能的,只是它很容易出错,而且您必须习惯于调试这样的问题。在</p>