Skip to content

Calling python code from c++ gives unexpected number of references #100334

Closed as not planned
@jhaggle

Description

@jhaggle

I am running this C++ 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

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?

This is how the local variables look when the code reaches the line Py_XDECREF(pValue) but before it executes:

enter image description here

After executing Py_XDECREF(pValue); it looks like this:

enter image description here

After executing Py_XDECREF(pFunc); it looks like this:

enter image description here

Finally when executing 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>

enter image description here

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions