#define PY_SSIZE_T_CLEAN #include #include "PyWrap.h" #include #include #include #include #include "PyHelper.hpp" namespace pywrap { namespace np = boost::python::numpy; PyWrap* PyWrap::wrapper = nullptr; std::mutex PyWrap::mutex; PyWrap* PyWrap::GetInstance() { std::lock_guard lock(mutex); if (wrapper == nullptr) { std::cout << "Creando instancia" << std::endl; wrapper = new PyWrap(); std::cout << "Instancia creada" << std::endl; } return wrapper; } PyWrap::PyWrap() { PyStatus status = initPython(); if (PyStatus_Exception(status)) { throw std::runtime_error("Error initializing Python"); } np::initialize(); } PyWrap::~PyWrap() { for (const auto& item : moduleClassMap) { Py_DECREF(std::get<0>(item.second)); Py_DECREF(std::get<1>(item.second)); Py_DECREF(std::get<2>(item.second)); } Py_Finalize(); } void PyWrap::importClass(const std::string& moduleName, const std::string& className) { std::cout << "Importando clase" << std::endl; auto result = moduleClassMap.find({ moduleName, className }); if (result != moduleClassMap.end()) { return; } std::cout << "No estaba en el mapa" << std::endl; PyObject* module = PyImport_ImportModule(moduleName.c_str()); if (PyErr_Occurred()) { errorAbort("Could't import module " + moduleName); } PyObject* classObject = PyObject_GetAttrString(module, className.c_str()); if (PyErr_Occurred()) { errorAbort("Couldn't find class " + className); } PyObject* instance = PyObject_CallObject(classObject, NULL); if (PyErr_Occurred()) { errorAbort("Couldn't create instance of class " + className); } moduleClassMap[{moduleName, className}] = { module, classObject, instance }; std::cout << "Clase importada" << std::endl; } void PyWrap::clean(const std::string& moduleName, const std::string& className) { std::cout << "Limpiando" << std::endl; auto result = moduleClassMap.find({ moduleName, className }); if (result == moduleClassMap.end()) { return; } std::cout << "--> Limpiando" << std::endl; Py_DECREF(std::get<0>(result->second)); Py_DECREF(std::get<1>(result->second)); Py_DECREF(std::get<2>(result->second)); moduleClassMap.erase(result); std::cout << "Limpieza terminada" << std::endl; } void PyWrap::errorAbort(const std::string& message) { std::cout << message << std::endl; PyErr_Print(); exit(1); } PyObject* PyWrap::getClass(const std::string& moduleName, const std::string& className) { auto item = moduleClassMap.find({ moduleName, className }); if (item == moduleClassMap.end()) { errorAbort("Module " + moduleName + " and class " + className + " not found"); } std::cout << "Clase encontrada" << std::endl; return std::get<2>(item->second); } std::string PyWrap::callMethodString(const std::string& moduleName, const std::string& className, const std::string& method) { std::cout << "Llamando método " << method << std::endl; PyObject* instance = getClass(moduleName, className); PyObject* result; if (!(result = PyObject_CallMethod(instance, method.c_str(), NULL))) errorAbort("Couldn't call method " + method); std::string value = PyUnicode_AsUTF8(result); std::cout << "Result: " << value << std::endl; Py_DECREF(result); return value; } std::string PyWrap::version(const std::string& moduleName, const std::string& className) { return callMethodString(moduleName, className, "version"); } void PyWrap::fit(const std::string& moduleName, const std::string& className, PyObject* X, PyObject* y) { std::cout << "Llamando método fit" << std::endl; PyObject* instance = getClass(moduleName, className); PyObject* result; std::string method = "fit"; if (!(result = PyObject_CallMethodObjArgs(instance, PyUnicode_FromString(method.c_str()), X, y, NULL))) errorAbort("Couldn't call method fit"); Py_DECREF(result); } PyObject* PyWrap::predict(const std::string& moduleName, const std::string& className, PyObject* X) { std::cout << "Llamando método predict" << std::endl; PyObject* instance = getClass(moduleName, className); PyObject* result; std::string method = "predict"; if (!(result = PyObject_CallMethodObjArgs(instance, PyUnicode_FromString(method.c_str()), X, NULL))) errorAbort("Couldn't call method predict"); return result; // The caller has to decref the result } double PyWrap::score(const std::string& moduleName, const std::string& className, PyObject* X, PyObject* y) { std::cout << "Llamando método score" << std::endl; PyObject* instance = getClass(moduleName, className); PyObject* result; std::string method = "score"; if (!(result = PyObject_CallMethodObjArgs(instance, PyUnicode_FromString(method.c_str()), X, y, NULL))) errorAbort("Couldn't call method score"); return PyFloat_AsDouble(result); } // void PyWrap::doCommand2() // { // PyObject* list = Py_BuildValue("[s]", "Stree"); // // PyObject* module = PyImport_ImportModuleEx("stree", NULL, NULL, list); // PyObject* module = PyImport_ImportModule("stree"); // if (PyErr_Occurred()) { // PyErr_Print(); // cout << "Fails to obtain the module.\n"; // return; // } // cout << "Antes de empezar" << endl; // if (module != nullptr) { // cout << "Lo consiguió!!!" << endl; // // dict is a borrowed reference. // auto pdict = PyModule_GetDict(module); // if (pdict == nullptr) { // cout << "Fails to get the dictionary.\n"; // return; // } // Py_DECREF(module); // PyObject* pKeys = PyDict_Keys(pdict); // PyObject* pValues = PyDict_Values(pdict); // map my_map; // cout << "size: " << PyDict_Size(pdict) << endl; // char* cstr_key = new char[100]; // char* cstr_value = new char[500]; // for (Py_ssize_t i = 0; i < PyDict_Size(pdict); ++i) { // PyArg_Parse(PyList_GetItem(pKeys, i), "s", &cstr_key); // PyArg_Parse(PyList_GetItem(pValues, i), "s", &cstr_value); // //cout << cstr<< " "<< cstr2 <