I am running the C++ code below and it works fine if I comment out the Py_XDECREF
lines. I suppose, however, that it causes memory leaks in such a case. When the Py_XDECREF
lines are commented in, the code execution behaves unexpected. First of all, I don't understand the number of references. Why is there for example seven references to pName? Second, why do I get a negative refcount-error when using Py_XDECREF
? As I understood Py_XDECREF
should be safe in this respect, and the current error should only be possible if I use Py_DECREF
? Third and most importantly: How to I change the code so that it works?
When executing the line Py_XDECREF(pDict);
I get the following error:
D:\a\1\s\Include\object.h:497: _Py_NegativeRefcount: Assertion failed: object has negative ref count
<object at 0000018CA6726410 is freed>
Fatal Python error: _PyObject_AssertFailed: _PyObject_AssertFailed
Python runtime state: initialized
Current thread 0x000086b0 (most recent call first):
<no Python frame>
Here is the code:
#include <Python.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
int main(int argc, char** argv) {
// 1) initialize Python
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append(\".\")");
PyRun_SimpleString("print(sys.path)");
// 2) Import the python module
PyObject* pName = PyUnicode_FromString("module1");
assert(pName != NULL);
PyObject* pModule = PyImport_Import(pName);
assert(pModule != NULL);
// 3) Get a reference to the python function to call
PyObject* pDict = PyModule_GetDict(pModule);
assert(pDict != NULL);
PyObject* pFunc = PyDict_GetItemString(pDict, (char*)"getInteger");
assert(pFunc != NULL);
// 4) Call function
PyObject* pValue = PyObject_CallObject(pFunc, NULL);
Py_XDECREF(pValue);
Py_XDECREF(pFunc);
Py_XDECREF(pDict);
Py_XDECREF(pModule);
Py_XDECREF(pName);
Py_Finalize();
The imported module is called module1.py
and has this content:
def getInteger():
print('Python function getInteger() called')
c = 100*50/30
return c
PyModule_GetDict
returns a borrowed reference . You should not decrement the reference count of a borrowed reference, so the error is entirely expected: the ref count can't be decremented because it was already zero.
However, you can simplify it by using PyObject_GetAttrString(pModule, "getInteger")
directly instead of going through pDict
.
You should also write proper error handing, since assert
only works in Debug builds and becomes no-op in Release mode.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.