Python.h को C ++ में शामिल करें

Dec 07 2020

जब मैं अपने क्यूटी सी ++ प्रोग्राम में एक पायथन स्क्रिप्ट को एम्बेड करने की कोशिश कर रहा था, तो पायथन को शामिल करने की कोशिश करते समय मैं कई समस्याओं में भाग जाता हूं। निम्नलिखित विशेषताएं, मैं प्रदान करना चाहूंगा:

  • अजगर शामिल करें
  • पायथन स्ट्रिंग्स निष्पादित करें
  • पायथन लिपियों को निष्पादित करें
  • पाइथन लिपियों के तर्क के साथ निष्पादित करें
  • यह भी काम करना चाहिए जब पायथन को तैनात मशीन पर स्थापित नहीं किया गया है

इसलिए मैंने समाधान खोजने की कोशिश करने के लिए इंटरनेट पर खोज की। और बहुत सारे प्रश्न और ब्लॉग मिले, लेकिन गैर ने उन्हें मेरी सभी समस्याओं को कवर किया है और मुझे अभी भी कई घंटे और बहुत निराशा हुई है। इसलिए मुझे अपने पूर्ण समाधान के साथ एक StackOverflow प्रविष्टि लिखना है ताकि यह मदद कर सके और आपके सभी काम में तेजी ला सके :)

जवाब

3 Olgidos Dec 07 2020 at 22:01

(यह उत्तर और इसके सभी कोड उदाहरण गैर-क्यूटी वातावरण में भी काम करते हैं। केवल 2. और 4. क्यूटी विशिष्ट हैं)

  1. पायथन को डाउनलोड और इंस्टॉल करें https://www.python.org/downloads/release
  2. अपनी परियोजना की .pro फ़ाइल को बदल दें और निम्न पंक्तियाँ जोड़ें (अपने सही अजगर पथ के लिए संपादित करें):
INCLUDEPATH = "C:\Users\Public\AppData\Local\Programs\Python\Python39\include" 
LIBS += -L"C:\Users\Public\AppData\Local\Programs\Python\Python39\libs" -l"python39"
  1. उदाहरण। मुख्य कोड:
#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> इसके बजाय निम्नलिखित कोड का उपयोग करें। (पायथन से स्लॉट अन्यथा क्यूटी स्लॉट के साथ संघर्ष करेंगे
#pragma push_macro("slots")
#undef slots
#include <Python.h>
#pragma pop_macro("slots")
  1. संकलन करने के बाद, अपने संकलन फ़ोल्डर में python3.dll, python39.dll, साथ ही DLL और Lib Python फ़ोल्डर जोड़ें। आप उन्हें अपने पायथन इंस्टॉलेशन के रूट डायरेक्टरी में पा सकते हैं। यह आपको एम्बेडेड सी ++ कोड चलाने की अनुमति देगा, यहां तक ​​कि जब अजगर स्थापित नहीं होता है।

इन चरणों के साथ, मैं 64 बिट MinGW और MSVC कंपाइलर के साथ Qt में अजगर चलाने में सक्षम था। डिबग मोड में केवल MSVC को अभी भी एक समस्या मिली।

आगे की:

यदि आप पाइथन लिपि में तर्क पारित करना चाहते हैं, तो आपको निम्नलिखित फ़ंक्शन की आवश्यकता है (यह आपके कोड में आसान कॉपी-पेस्ट किया जा सकता है):

/*!
 * \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);

टेस्ट फोल्डर में टेस्टफोरो स्क्रिप्ट के साथ:

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