如何创建和使用存储为c++;对象 因此,我想研究一个C++项目,在这里我需要调用一个Python模块,保存它作为一个对象,并多次调用它的一个方法。下面您可以找到包含python对象的类的代码。目前,它是在for循环中实现的,该循环多次调用该方法。实例化该类以及对该类的第一次调用工作正常。但是,在for循环的第一个循环完成后,程序崩溃,并出现“free():invalid size”或有时“double free or corrupt”的错误。我尝试使用valgrind来追踪内存泄漏,但是我得到了很多关于pythonCApi调用的痕迹,我真的不明白 #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;} #包括 #包括 #包括 #包括“predictor.hpp” 使用名称空间std; 预测器::预测器() { Py_初始化(); pName=PyString_FromString(“预测器”); pModule=PyImport\u Import(pName); Py_XDECREF(pName); if(pModule==nullptr){ PyErr_Print(); std::cerr
编写Python C/C++代码最关键的部分是正确计算引用。Python区分不同类型的引用,即如何创建和使用存储为c++;对象 因此,我想研究一个C++项目,在这里我需要调用一个Python模块,保存它作为一个对象,并多次调用它的一个方法。下面您可以找到包含python对象的类的代码。目前,它是在for循环中实现的,该循环多次调用该方法。实例化该类以及对该类的第一次调用工作正常。但是,在for循环的第一个循环完成后,程序崩溃,并出现“free():invalid size”或有时“double free or corrupt”的错误。我尝试使用valgrind来追踪内存泄漏,但是我得到了很多关于pythonCApi调用的痕迹,我真的不明白 #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;} #包括 #包括 #包括 #包括“predictor.hpp” 使用名称空间std; 预测器::预测器() { Py_初始化(); pName=PyString_FromString(“预测器”); pModule=PyImport\u Import(pName); Py_XDECREF(pName); if(pModule==nullptr){ PyErr_Print(); std::cerr,python,c++,python-embedding,Python,C++,Python Embedding,编写Python C/C++代码最关键的部分是正确计算引用。Python区分不同类型的引用,即新的、被盗的和借用的引用 对于您调用的每个API函数,您都必须检查文档以查看它返回的引用类型(如果有) 新引用属于调用者,因此使用Py\u XDECREF通过减少引用计数来释放对象是正确的。确保调用Py\u XDECREF不超过一次,除非在其间增加引用计数。在错误处理中,Py\u XDECREF(pModule)发生两次,例如,因为在错误情况下不返回,所以只需继续 借用的引用归其他人所有,并且引用计数没
新的
、被盗的
和借用的
引用
对于您调用的每个API函数,您都必须检查文档以查看它返回的引用类型(如果有)
新引用属于调用者,因此使用Py\u XDECREF
通过减少引用计数来释放对象是正确的。确保调用Py\u XDECREF
不超过一次,除非在其间增加引用计数。在错误处理中,Py\u XDECREF(pModule)
发生两次,例如,因为在错误情况下不返回,所以只需继续
借用的引用归其他人所有,并且引用计数没有为您增加。因此,只有在您自己增加引用计数之后,调用Py_XDECREF
才有效
PyModule\u GetDict(pModule)
返回一个借用的引用。您不增加引用计数,但稍后使用Py\u XDECREF(dict)
将其递减。对于PyDict\u GetItemString(dict,“predictor”)
,它返回一个借用的引用,而您使用Py\u XDECREF(python\u类)将其递减
我的假设是,在这两种情况下(
dict
,python\u类
),借用的引用都属于使用PyImport\u导入(pName)导入的模块pModule
)
。因此,只要使用pModule
拥有的借用引用,就很可能不能减少pModule
引用计数。一旦不再使用那些借用的引用,可以使用Py\u XDECREF
释放pModule
。或者,可以增加引用借来的引用计数,但只要你保持pModule
,这就没有必要了。好的,所以你的建议解决了第一个内存错误(通过删除借来的代码的所有减量,并删除重复的减量)。然而,之后我得到一个错误,上面写着free()无效的大小。这与我这里的代码或其他什么有关。我重新创建了您的示例。当我删除dict
和python_类的不正确的PyXDECREF
时,我无法再重现内存问题。valgrind确实报告内存错误。以前,它报告了。我还移动了pModule
PyXDECREF
在最后一次使用逻辑上属于它的借用引用之后-也就是在实例创建块之后。在这种情况下没有可识别的错误,但基于所有权,这是正确的做法。许多示例似乎将pModule
引用保留到去初始化,但在引用方面,我看不到错误需要这样做。