Встраивание скрипта Python3.5 в приложение QT - PullRequest
0 голосов
/ 09 мая 2019

Я пытаюсь встроить скрипт Python (python 3.5), содержащий класс, в мое приложение QT c ++.До того, как попробовать GUI, я пробовал простое консольное приложение.Проблема в том, что когда я выбрал «Консольное приложение QT» в качестве нового типа проекта, код зависает, но если я выбрал «Простое приложение C ++» (опция проекта не QT), программа работает так, как предполагалось!

Python Script:

import numpy as np
import dlib

# some other imports that also imports other modules

class myclass:

    def __init__(self, path1, path2, path3, use_Test=True):

        self.p1 = path1
        self.p2 = path2
        self.p3 = path3

        self.test = use_Test

    # some other functions

    def add(self, x, y):
        return x+y

это код, который я пытаюсь использовать в простом приложении C ++:

сначала в файле .pro:

TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt

SOURCES += main.cpp

INCLUDEPATH += /usr/include/python3.5
LIBS += -L/usr/lib/python3.5/config-3.5m-x86_64-linux-gnu -lpython3.5

Код C ++:

#include <iostream>
#include <Python.h>


using namespace std;

int main()
{
    setenv("PYTHONPATH", ".", 1);

    Py_Initialize();

    PyObject* module = PyImport_ImportModule("myscript");
    assert(module != NULL);

    PyObject* dict = PyModule_GetDict(module);
    assert(module != NULL);
    Py_DECREF(module);

    PyObject* python_class = PyDict_GetItemString(dict, "myclass");
    assert(python_class != NULL);
    Py_DECREF(dict);

    PyObject* engine;
    if (PyCallable_Check(python_class))
    {
        PyObject *args = Py_BuildValue("(sss)", "s1", "s2", "s3");
        PyObject *keywords = PyDict_New();
        PyDict_SetItemString(keywords, "tester", Py_False);

        engine = PyObject_Call(python_class, args, keywords);
        Py_DECREF(python_class);
        Py_DECREF(args);
        Py_DECREF(keywords);
    }
    else
    {
        std::cout << "Cannot instantiate the Python class" << std::endl;
        Py_DECREF(python_class);
        return 1;
    }

    PyObject *value = PyObject_CallMethod(engine, "add", "(ii)", 2, 4);

    int result = PyLong_AsLong(value);

    cout<<"Result = "<<result<<endl;

    cout << "Hello World!" << endl;

    Py_Finalize();

    return 0;
}

Этот код работает правильно, и я получаю требуемый результат от функции добавления.но, переходя к консольному приложению QT, код становится:

PRO:

QT -= gui

CONFIG += c++11 console
CONFIG -= app_bundle

CONFIG += no_keywords    #Solve Python SLOT ISSUE

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += main.cpp


INCLUDEPATH += /usr/include/python3.5
#INCLUDEPATH += /usr/local/lib/python3.5/dist-packages/numpy/core/include/numpy
LIBS += -L/usr/lib/python3.5/config-3.5m-x86_64-linux-gnu -lpython3.5

C ++

#include <QCoreApplication>

#include <Python.h>


#include <QDir>
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    setenv("PYTHONPATH", ".", 1);

    Py_Initialize();

    PyObject* module = PyImport_ImportModule("myscript");
    assert(module != NULL);

    PyObject* dict = PyModule_GetDict(module);
    assert(module != NULL);
    Py_DECREF(module);

    PyObject* python_class = PyDict_GetItemString(dict, "myclass");
    assert(python_class != NULL);
    Py_DECREF(dict);

    PyObject* engine;
    if (PyCallable_Check(python_class))
    {
        PyObject *args = Py_BuildValue("(sss)", "s1", "s2", "s3");
        PyObject *keywords = PyDict_New();
        PyDict_SetItemString(keywords, "tester", Py_False);

        engine = PyObject_Call(python_class, args, keywords);
        Py_DECREF(python_class);
        Py_DECREF(args);
        Py_DECREF(keywords);
    }
    else
    {
        std::cout << "Cannot instantiate the Python class" << std::endl;
        Py_DECREF(python_class);
        return 1;
    }

    PyObject *value = PyObject_CallMethod(engine, "add", "(ii)", 2, 4);

    int result = PyLong_AsLong(value);

    cout<<"Result = "<<result<<endl;

    cout << "Hello World!" << endl;

    Py_Finalize();

    return a.exec();

}

, но всякий раз, когда я пытаюсь запустить код, происходит сбой (происходит сбой в модуле PyObject * module = PyImport_ImportModule ("myscript"); строка)

Я искал решение SO, и в ответе предлагалось добавить следующее после Py_Initialize ();

QString qs = QDir::currentPath();
std::wstring ws = qs.toStdWString();
PySys_SetPath(ws.data());

Это помогло не разбить код, но теперь все мои импорты на python являются ошибками (т.е.: ImportError: нет модуля с именем 'numpy')

Чего мне не хватает в приложении QT?Есть ли конфликт между QT и Python?

...