So as the title sort of suggests, I am working on a c++ project where I need to call a python module, save it as an object, and call one of its methods multiple times. Below you can find the code for the class, which contains the python object. Currently, it is implemented inside of a for loop which calls the method multiple times. Instantiating the class works fine, along with the first call to the class. However, upon completion of the first loop of the for loop the program crashes with an error along the lines of "free(): invalid size" or sometimes "double free or corruption". I tried using valgrind to try and track down the memory leak, but I get a lot of traces to pythonCApi calls that I dont really understand.
#include <python2.7/Python.h>
#include <iostream>
#include <algorithm>
#include "predictor.hpp"
using namespace std;
predictor::predictor()
{
Py_Initialize();
pName = PyString_FromString("predictor");
pModule = PyImport_Import(pName);
Py_XDECREF(pName);
if (pModule == nullptr) {
PyErr_Print();
std::cerr << "Fails to import the module predictor, check installation.\n";
}
// dict is a borrowed reference.
dict = PyModule_GetDict(pModule);
if (dict == nullptr) {
PyErr_Print();
std::cerr << "Fails to get the dictionary, check predictor installation.\n";
Py_XDECREF(pModule);
}
Py_XDECREF(pModule);
// Builds the name of a callable class
python_class = PyDict_GetItemString(dict, "Predictor");
if (python_class == nullptr || python_class == NULL) {
PyErr_Print();
std::cerr << "Fails to get the Python class, check predictor installation.\n";
Py_XDECREF(dict);
}
Py_XDECREF(dict);
// Creates an instance of the class
if (PyCallable_Check(python_class)) {
object = PyObject_CallObject(python_class, nullptr);
if (object == NULL)
{
cerr << "Fails to create object.";
Py_XDECREF(python_class);
}
Py_XDECREF(python_class);
} else {
PyErr_Print();
std::cout << "Cannot instantiate the Python class" << std::endl;
Py_XDECREF(python_class);
}
pMethod = PyString_FromString("predict_all");
}
predictor::~predictor()
{
Py_XDECREF(pMethod);
Py_XDECREF(object);
Py_Finalize();
}
long predictor::predict(string rule)
{
PyObject *pRule = PyString_FromString(rule.c_str());
PyObject *value = PyObject_CallMethodObjArgs(object, pMethod, pRule, NULL);
long endValue = PyInt_AsLong(value);
if (endValue == -1)
{
if(!PyErr_Occurred())
{
PyErr_Print();
cerr << "";
Py_XDECREF(value);
Py_XDECREF(pRule);
return NULL;
}
//PyErr_Print();
}
Py_XDECREF(value);
Py_XDECREF(pRule);
return endValue;}