【问题标题】:Embedding Python in C++. Passing vector of strings receving a list of lists在 C++ 中嵌入 Python。传递接收列表列表的字符串向量
【发布时间】:2014-10-06 02:40:00
【问题描述】:

我有一个用 C++ 编写的 Windows 应用程序。我有一个字符串向量,我需要将其传递给 python 脚本进行处理。我知道如何将 python 嵌入到具有简单类型的 C++ 中,但我正在研究如何创建一个与字符串向量等效的 python 对象。我在看类似的东西:

for (size_t i = 0; i < myvector.size(); ++i)
{
    PyUnicode_FromString.append(myvector[i]);
}

或许

for (size_t i = 0; i < myvector.size(); ++i)
{
    pValue = PyUnicode_FromString(myvector[i]);
    pyTuple_SetItem(myvector.size(), i, pValue);
}

向量几乎不会变得非常大(我会说最多 100 个项目)。目前我只是保存一个文本文件,我让 python 脚本打开它并处理它,这显然不是很好,但它告诉我其他一切都按计划工作。 Python 脚本的处理为每个项目生成 4 个值(3 个字符串和 1 个整数(长整数))。我还需要返回这个主 C++ 程序,我不知道该怎么做。 (编辑)在审查了可能的选项之后,我正在考虑一个列表列表(因为字典没有排序并且需要更多的解析操作)应该可以解决问题,但我不知道如何在 C++ 中解码它程序(现在再次通过文件写入/读取完成,所以我知道它有效)。如果有人这样做过,请您提供小代码 sn-ps,以便我可以根据我的需要进行调整。我还应该提到我不能使用 boost 库(最好也没有 SWIG)——所以,基本上是在 Python C-API 中完成的。我所见过的所有关于子流程或 NumPy 的例子我都不相信(可能是错误的)适用于我的案例。

【问题讨论】:

    标签: python c++ vector embedding python-c-api


    【解决方案1】:

    好吧,我设法弄清楚我想要什么。下面是我正在尝试做的一个完整的工作示例。然而,答案并不完整,因为缺少很多错误检查,更重要的是缺少一些 Py_DECREF。我会尝试抓住它们并在我弄清楚时进行更新,但如果有人精通这类事情可以提供帮助,那将不胜感激。如下:

    Python 脚本:(testingoutput.py) 该脚本接收一个字符串列表,对于每个字符串,它返回 3 个随机字符串(来自提供的列表)和一个随机整数。格式为:[[sssi],]

    import random
    import string
    
    def get_list_send_list(*input_list):  
        outer_list = []   
        for key in input_list:        
            inner_list = []
            # from here, your program should produce the data you want to retrieve and insert it    in a list
            # for this example, a list comprised of 3 random strings and 1 random number is returned
            for i in range (0, 3):
                some_words = random.choice(["red", "orange", "yellow", "green", "blue", "purple", "white", "black"])
                inner_list.append(some_words)        
            inner_list.append(random.randint(1,10))
            outer_list.append(inner_list)
        return outer_list
    

    这是 cpp 文件。与 Python C API 示例基本相同,但稍作修改以适应列表。我不需要这个来满足我的需要,但我在这里和那里进行了一些类型检查,以使任何可能需要这种东西的人受益。

    #include <Python.h>
    #include <iostream>
    #include <vector>
    
    int main(int argc, char *argv[])
    {
        PyObject *pName, *pModule, *pFunc;
        PyObject *pArgs, *pValue;
        PyObject *pList, *pListItem, *pyString; 
    
        char* strarray[] = {"apple", "banana", "orange", "pear"};
        std::vector<std::string> strvector(strarray, strarray + 4);
        std::string pyFile = "testingoutput";
        std::string pyFunc = "get_list_send_list";
    
        Py_Initialize();
        pName = PyUnicode_FromString(pyFile.c_str());
        /* Error checking of pName left out */
    
        pModule = PyImport_Import(pName);
        Py_DECREF(pName);
    
        if (pModule != NULL)
        {
            pFunc = PyObject_GetAttrString(pModule, pyFunc.c_str());
            /* pFunc is a new reference */
    
            if (pFunc && PyCallable_Check(pFunc)) {
                pArgs = PyTuple_New(strvector.size());
          for (size_t i = 0; i < strvector.size(); ++i)
                {
                    pValue = PyUnicode_FromString(strvector[i].c_str());
                    if (!pValue)
                    {
                        Py_DECREF(pArgs);
                        Py_DECREF(pModule);
                        fprintf(stderr, "Cannot convert argument\n");
                        return 1;
                    }
                    /* pValue reference stolen here: */         
                    PyTuple_SetItem(pArgs, i, pValue);
                }           
    
                pValue = PyObject_CallObject(pFunc, pArgs);
                Py_DECREF(pArgs);
    
          if (pValue != NULL)
          {
        int py_list_size = PyList_Size(pValue);
        int sub_list_size = 0;
        std::cout << "Retrieving content..."<< "\n";
        for(Py_ssize_t i = 0; i < py_list_size; ++i)
        {
            pList = PyList_GetItem(pValue, i);
            sub_list_size = PyList_Size(pList);
            // verify if the subitem is also a list - if yes process it
            if(PyList_Check(pList))
            {
                std::cout << "********** " << i << " **********\n";
                for(Py_ssize_t j = 0; j < sub_list_size; ++j)
                {
                    pListItem = PyList_GetItem(pList, j);
                    // verify if the item is a string or a number
                    if(PyUnicode_Check(pListItem))
                    {
                         // "Error ~" does nothing here but it should be defined to catch errors
                         pyString = PyUnicode_AsEncodedString(pListItem, "utf-8", "Error ~");
                         const char *tmpCstChar =  PyBytes_AS_STRING(pyString);
                         std::cout << "Item " << j << ": " << tmpCstChar << "\n";
                     }
                     else if(PyLong_Check(pListItem))
                     {
                         int pyNumber = PyLong_AsLong(pListItem);
                         std::cout << "Item " << j << ": " << pyNumber << "\n";
                     }
                 }
             }
             else
             {
                 std::cout << "This item is not a list\n";
             }
         }
         Py_DECREF(pValue);
         }
                else
                {
                    Py_DECREF(pFunc);
                    Py_DECREF(pModule);
                    PyErr_Print();
                    fprintf(stderr,"Call failed\n");
                    return 1;
                }
            }
            else
            {
                if (PyErr_Occurred())
                    PyErr_Print();
                fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]);
            }
            Py_XDECREF(pFunc);
            Py_DECREF(pModule);
        }
        else
        {
            PyErr_Print();
            fprintf(stderr, "Failed to load \"%s\"\n", argv[1]);
            return 1;
        }
        Py_Finalize();
        return 0;
    }
    

    同样,缺少一些错误检查,更重要的是,缺少一些 Py_DECREF。即这个程序正在泄漏内存。如果您知道如何解决此问题,我们将不胜感激。

    【讨论】:

    • 我在Failed to load "P�"` 与ImportError: Import by filename is not supported. 崩溃
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-05
    • 1970-01-01
    • 1970-01-01
    • 2018-12-08
    • 2018-04-05
    • 2020-05-20
    • 1970-01-01
    相关资源
    最近更新 更多