Python 3: проблемы со строками Python/C API

Я пытаюсь использовать API Python/C для запуска функции Python, которая возвращает строку. Я хочу сохранить эту возвращаемую строку в переменной C++, но не могу заставить ее работать. Я использую Python 3, и похоже, что метод PyString_FromString() больше не работает. Вот мой код:

int main(int argc, char *argv[])
{
    PyObject *pName, *pModule, *pDict, *pFunc, *pValue;

    Py_Initialize();

    pName = PyUnicode_FromString("ocr");

    pModule = PyImport_Import(pName);

    pDict = PyModule_GetDict(pModule);

    pFunc = PyDict_GetItemString(pDict, "get_text");

    pValue = PyUnicode_FromString("ocr_noise.png");
    pValue = PyObject_CallObject(pFunc, pValue);

    std::string result = PyUnicode_FromObject(pValue);

    Py_DECREF(pModule);
    Py_DECREF(pName);
    Py_DECREF(pValue);

    Py_Finalize();

    return 0;
}

Файл Python называется ocr.py, а функция, которую я пытаюсь вызвать, называется get_text(value). Я пытаюсь передать "ocr_noise.png" в качестве аргумента. Есть идеи, что мне делать?

РЕДАКТИРОВАТЬ 2: мне не нужно использовать std::string как в коде. Что еще я могу использовать для хранения строки, возвращаемой функцией?


person MarcioPorto    schedule 15.11.2015    source источник
comment
Что вы имеете в виду, говоря, что метод PyUnicode_FromString() больше не работает? Вы получаете исключение? Сегфолт? Что-то другое?   -  person Andrea Corbellini    schedule 15.11.2015
comment
Я имел в виду PyString_FromString(). Виноват.   -  person MarcioPorto    schedule 16.11.2015
comment
В Python 3 нет такой вещи, как PyString_FromString.   -  person Andrea Corbellini    schedule 16.11.2015
comment
Итак, как мне заставить это работать в Python 3?   -  person MarcioPorto    schedule 16.11.2015
comment
Рассматривали ли вы возможность использования существующей библиотеки-оболочки, такой как Boost.Python, вместо низкоуровневого C API? Это должно сделать эти вещи намного проще. Тем не менее, пожалуйста, прочитайте руководство здесь, ваш вопрос по определению не по теме, как там объясняется.   -  person Ulrich Eckhardt    schedule 16.11.2015
comment
Я думаю, вы хотите использовать PyUnicode_AS_DATA, который возвращает std::wstring   -  person Andrea Corbellini    schedule 16.11.2015
comment
а также есть PyUnicode_AsUTF8, если вы действительно хотите string   -  person Andrea Corbellini    schedule 16.11.2015


Ответы (1)


Очень важно проверять возвращаемые значения всех функций Python. Python возвращает nullptr, если произошла ошибка. Так что PyUnicode_FromString() отлично работает в вашем коде. Это просто segfaults, потому что pValue — это nullptr, которое вы получили от PyObject_CallObject(). Помещение PyErr_Print() сразу после этого вызова печатает:

TypeError: argument list must be a tuple

Вам нужно передать кортеж объектов в качестве аргумента, а не один str. Вместо этого вы можете использовать PyObject_CallFunction(pFunc, "O", pValue) или PyObject_CallFunction(pFunc, "s", "ocr_noise.png").

Кроме того, загляните в PyImport_ImportModule(). более того

std::string result = PyUnicode_FromObject(pValue);

не должен даже компилироваться, так как возвращает PyObject *, а не string.

person tynn    schedule 15.11.2015
comment
Что мне делать, чтобы сохранить возвращенную строку? - person MarcioPorto; 16.11.2015
comment
PyUnicode_FromObject() может быть вообще бесполезным. pValue уже должен быть объектом Unicode. См. Чистый способ преобразования Python 3 Unicode в std::string для более подробной информации о том, как получить строку c из объекта Unicode Python. - person tynn; 16.11.2015