Как исправить PyImport_Import в C++ (исключение в python35.dll)

Я пробую действительно простую программу «hello world», которая должна встраивать скрипт python в мое консольное приложение C++, но она терпит неудачу в pModule = PyImport_Import(pName); с неуказанным исключением «Место чтения нарушения доступа ...»

Я уже смог запустить PyRun_SimpleFile() для скрипта python без определений и возвратов, но для моего будущего приложения мне нужен метод python с возвратами, поэтому PyRun_SimpleFile() не вариант.

Мой код, основанный на этом введении это:

main.cpp

#include "stdafx.h"
#include <stdlib.h>
#include <Python.h>

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

    pName = PyUnicode_FromString("HelloWorld");
    pModule = PyImport_Import(pName);
    Py_XDECREF(pName);

    if (pModule)
    {
        pFunc = PyObject_GetAttrString(pModule, "getInteger");
        if (pFunc && PyCallable_Check(pFunc))
        {
            pValue = PyObject_CallObject(pFunc, NULL);
            printf_s("C: getInteger() = %ld\n", PyLong_AsLong(pValue));
            Py_XDECREF(pValue);
        }
        else
        {
            printf("ERROR: function getInteger()\n");
        }
        Py_XDECREF(pFunc);
    }
    else
    {
        printf_s("ERROR: Module not imported\n");
    }

    Py_XDECREF(pModule);

    Py_Finalize();
    return 0;
}

HelloWorld.py (в месте отладки моего решения VS2015):

def getInteger():
    print('Python function getInteger() called')
    c = 100*2
    return c

person shup    schedule 31.05.2019    source источник


Ответы (1)


Ну, я считаю, что в вашем коде отсутствуют некоторые инструкции, например Py_Initialize. Я бы также использовал PyImport_ImportModule вместо PyImport_Import. Посмотрите эту последовательность, которую вы могли бы попробовать:

int main(int argc, char *argv[])
{
    Py_SetPythonHome(L"path/to/python/folder");
    Py_Initialize();
    //PySys_SetArgv(argc, argv); //optional, argv must be wchar_t
    PyObject *pFunc, *pValue;

    pModule = PyImport_ImportModule("HelloWorld");

    if (pModule)
    {
        pFunc = PyObject_GetAttrString(pModule, "getInteger");
        if (pFunc && PyCallable_Check(pFunc))
        {
            pValue = PyObject_CallObject(pFunc, NULL);
            printf_s("C: getInteger() = %ld\n", PyLong_AsLong(pValue));
            Py_XDECREF(pValue);
        }
        else
        {
            printf("ERROR: function getInteger()\n");
        }
        Py_XDECREF(pFunc);
    }
    else
    {
        printf_s("ERROR: Module not imported\n");
    }

    Py_XDECREF(pModule);

    Py_Finalize();
    return 0;
}

Если все еще не работает, попробуйте добавить это после PyInitialize:

PyRun_SimpleString(
    "import os, sys \n"
    "sys.path.append(os.getcwd()) \n"
);

Также после PyInitialize вы можете проверить, инициализирован ли он с помощью Py_IsInitialized.

person João Paulo    schedule 31.05.2019
comment
Большое спасибо! Пропавший Py_Initialize решил это! Но теперь я застрял в нарушении доступа для чтения на Py_Finalize. Есть идеи и по этому поводу? - person shup; 31.05.2019
comment
Старайтесь не Py_XDECREF(pModule). Удалите эту строку и посмотрите, перестанет ли она падать. - person João Paulo; 31.05.2019
comment
Это не изменило его, к сожалению. Но я обнаружил, что куча портится, но я не могу понять, где? - person shup; 03.06.2019
comment
Поскольку это не связано с исходным вопросом, я решил открыть новый. Спасибо за вашу помощь! - person shup; 03.06.2019