Вставить / включить Python.h в C ++ [Полное руководство] (Python 3.9) (Windows) (Qt 5.15) [дубликат]

Dec 07 2020

Когда я пытался встроить скрипт Python в свою программу Qt C ++, я столкнулся с множеством проблем при попытке включить Python.h. Я хотел бы выделить следующие функции:

  • Включите python.h
  • Выполнить строки Python
  • Выполнение скриптов Python
  • Выполнение скриптов Python с аргументами
  • Он также должен работать, когда Python не установлен на развернутом компьютере.

Поэтому я поискал в Интернете, чтобы попытаться найти решение. И нашел много вопросов и блогов, но ни один из них не охватил все мои проблемы, и это все равно заняло у меня несколько часов и много разочарований. Вот почему я должен написать запись StackOverflow с моим полным решением, чтобы оно могло помочь и ускорить всю вашу работу :)

Ответы

3 Olgidos Dec 07 2020 at 22:01

(Этот ответ и все его примеры кода работают также в среде, отличной от Qt. Только 2. и 4. специфичны для Qt)

  1. Скачайте и установите Python https://www.python.org/downloads/release
  2. Измените файл .pro вашего проекта и добавьте следующие строки (отредактируйте правильный путь к Python):
INCLUDEPATH = "C:\Users\Public\AppData\Local\Programs\Python\Python39\include" 
LIBS += -L"C:\Users\Public\AppData\Local\Programs\Python\Python39\libs" -l"python39"
  1. Пример кода main.cpp:
#include <QCoreApplication>

#pragma push_macro("slots")
#undef slots
#include <Python.h>
#pragma pop_macro("slots")

/*!
 * \brief runPy can execut a Python string
 * \param string (Python code)
 */
static void runPy(const char* string){
    Py_Initialize();
    PyRun_SimpleString(string);
    Py_Finalize();
}

/*!
 * \brief runPyScript executs a Python script
 * \param file (the path of the script)
 */
static void runPyScript(const char* file){
    FILE* fp;
    Py_Initialize();
    fp = _Py_fopen(file, "r");
    PyRun_SimpleFile(fp, file);
    Py_Finalize();
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    runPy("from time import time,ctime\n"
      "print('Today is', ctime(time()))\n");

    //uncomment the following line to run a script
    //runPyScript("test/decode.py");

    return a.exec();
}
  1. Всякий раз, когда вы #include <Python.h> используйте вместо этого следующий код. (В противном случае слоты из Python будут конфликтовать со слотами Qt.
#pragma push_macro("slots")
#undef slots
#include <Python.h>
#pragma pop_macro("slots")
  1. После компиляции добавьте в папку компиляции файлы python3.dll, python39.dll, а также папки DLL и Lib Python. Вы можете найти их в корневом каталоге вашей установки Python. Это позволит вам запускать встроенный код C ++, даже если python не установлен.

С помощью этих шагов я смог запустить python в Qt с 64-битным компилятором MinGW и MSVC. Только MSVC в режиме отладки все еще оставалась проблемой.

СПОСОБСТВОВАТЬ:

Если вы хотите передать аргументы скрипту python, вам понадобится следующая функция (ее можно легко скопировать в код):

/*!
 * \brief runPyScriptArgs executs a Python script and passes arguments
 * \param file (the path of the script)
 * \param argc amount of arguments
 * \param argv array of arguments with size of argc
 */
static void runPyScriptArgs(const char* file, int argc, char *argv[]){
    FILE* fp;
    wchar_t** wargv = new wchar_t*[argc];
    for(int i = 0; i < argc; i++)
    {
        wargv[i] = Py_DecodeLocale(argv[i], nullptr);
        if(wargv[i] == nullptr)
        {
            return;
        }
    }
    Py_SetProgramName(wargv[0]);

    Py_Initialize();
    PySys_SetArgv(argc, wargv);
    fp = _Py_fopen(file, "r");
    PyRun_SimpleFile(fp, file);
    Py_Finalize();

    for(int i = 0; i < argc; i++)
    {
        PyMem_RawFree(wargv[i]);
        wargv[i] = nullptr;
    }

    delete[] wargv;
    wargv = nullptr;
}

Чтобы использовать эту функцию, назовите ее так (например, в своей основной):

    int py_argc = 2;
    char* py_argv[py_argc];

    py_argv[0] = "Progamm";
    py_argv[1] = "Hello";

    runPyScriptArgs("test/test.py", py_argc, py_argv);

Вместе со скриптом test.py в тестовой папке:

import sys

if len(sys.argv) != 2:
  sys.exit("Not enough args")

ca_one = str(sys.argv[0])
ca_two = str(sys.argv[1])
print ("My command line args are " + ca_one + " and " + ca_two)

вы получите следующий результат:

My command line args are Progamm and Hello