Приведу пример как я сделал в своем старом движке на C++ + python.
С++ вызывает интерпритатор python. Здесь исходники python можно править во время выполнения программы. Каждые новые полученные данные будут обрабатываться с внесенными правками в исходный код python без перезапуска.
Мало ли кому пригодится.
Функция вызывается каждый раз как приходят данные. Она упрощена до мест использования python.
int TrPluginImpl::trprocessing(ODS::IObject& from, ODS::IObject & to)
{
tparser = new TableParser();
tparser->init();
do {
if (tparser->dict_set_conf((char *) conn_conf->get_login(), (char *) conn_conf->get_password(), (char *) "input_python_psfoi", (char *) conn_conf->get_ip(), (char *) conn_conf->get_name()) == false) {
ret = -1;
break;
}
QString xml_tmb = (tparser->parse((char *) table.toStdString().c_str(),
(char *) table_name.toStdString().c_str(),
(char *) from.getStringAttr("uno").toStdString().c_str()).c_str());
ret = -1;
break;
}
} while (0);
tparser->clear();
delete tparser;
return ret;
}
Методы по работе с python.
TABLEPARSER_PATH путь до исходников python.
PyObject *TableParser::init() {
do {
// Инициализировать интерпретатор Python
Py_Initialize();
this->sys = PyImport_ImportModule("sys");
this->sys_path = PyObject_GetAttrString(sys, "path");
this->folder_path = PyUnicode_FromString((const char*) TABLEPARSER_PATH);
PyList_Append(this->sys_path, this->folder_path);
//PySys_SetPath((const wchar_t*) VPEPARSER_PATH);
// Построить объект имени
this->pName = PyUnicode_FromString("TableParser");
if (!this->pName) {
PyErr_Print();
break;
}
// Загрузить объект модуля
this->pModule = PyImport_Import(this->pName);
if (!pModule) {
PyErr_Print();
break;
}
// pDict – заимствованная ссылка
this->pDict = PyModule_GetDict(this->pModule);
// построить имя вызываемого класса
this->pClass = PyDict_GetItemString(this->pDict, (const char *) "TableParser");
// создать экземпляр класса
if (PyCallable_Check(this->pClass)) {
this->pInstance = PyObject_CallObject(this->pClass, NULL);
} else {
break;
}
return this->pInstance;
} while (0);
return NULL;
}
void TableParser::clear() {
// Вернуть ресурсы системе
Py_XDECREF(this->pInstance);
Py_XDECREF(this->pClass);
Py_XDECREF(this->pDict);
Py_XDECREF(this->pModule);
Py_XDECREF(this->pName);
Py_XDECREF(this->folder_path);
Py_XDECREF(this->sys_path);
Py_XDECREF(this->sys);
// Завершить интерпретатор Python
Py_Finalize();
}
std::string TableParser::parse(char *table, char *table_type, char *uno, char *uid, int id) {
/*
PyObject *pValue = PyObject_CallMethod(this->pInstance, (char *) "parse", (char *) "(ss)", table, table_type);
if (pValue != NULL) {
Py_XDECREF(pValue);
} else {
PyErr_Print();
}
return;
*/
std::string str;
PyObject *pStr = PyObject_CallMethod(this->pInstance, (char *) "parse", (char *) "(ssssi)", table, table_type, uno, uid, id);
if (pStr != NULL) {
//int count = (int) PyByteArray_Size(pStr);
PyObject* pResultRepr = PyObject_Repr(pStr);
str = (char *) PyBytes_AS_STRING(PyUnicode_AsEncodedString(pResultRepr, (char *) "utf-8", (char *) "ERROR"));
Py_XDECREF(pResultRepr);
Py_XDECREF(pStr);
} else {
PyErr_Print();
return std::string("[error]: python call method parse");
//PyErr_Print();
}
//Py_XDECREF(pStr);
find_and_replace(str, "\\n", "\n");
find_and_replace(str, "\\t", "\t");
str.erase(str.begin());
str.erase(str.end() - 1);
return str;
}
bool TableParser::dict_set_conf(char *_login, char *_password, char *_id, char *_ip, char *_name) {
bool ret = false;
PyObject *pVal = PyObject_CallMethod(this->pInstance, (char *) "dict_set_conf", (char *) "(sssss)", _login, _password, _id, _ip, _name);
if (pVal != NULL) {
ret = (bool) PyBool_Check(pVal);
Py_XDECREF(pVal);
} else {
PyErr_Print();
return ret;
}
return ret;
}