簡體   English   中英

如何使用 SIP 將 std::list 從 c++ 轉換為 python

[英]How to translate std::list from c++ to python with SIP

我正在使用帶有 python 3.8 的 SIP 版本 6.0.1 並具有給定的 c++11 API。 (在 Ubuntu 18.04 上)

目標是使用 python 將自定義結構指針(我也用 sip 翻譯的結構)存儲在 std::list 中。

我構建了一個小例子來說明我的情況:

std_list.sip 文件

%Module(name=std_list, language="C++")

%Include type_list.sip

%DefaultEncoding "UTF-8"

struct TestStruct {

%TypeHeaderCode
#include <std_list.h>
%End

    int test1;
    int test2;

    void printStruct() const;
    TestStruct();
};

typedef std::list<TestStruct*> ListTestStruct;

struct StructContainerLvl2 {

%TypeHeaderCode
#include <std_list.h>
%End

    ListTestStruct listTestStruct;
    StructContainerLvl2();
};

用於列表翻譯的 type_list.sip 文件

template<TYPE *>
%MappedType std::list<TYPE *> /TypeHint="List[TYPE]"/ {
%TypeHeaderCode
#include <list>
%End

%ConvertFromTypeCode
    PyObject *l;

    const sipTypeDef* kpTypeDef = sipFindType("TYPE");

    if (!kpTypeDef) {
        return NULL;
    }

    // Create the Python list of the correct length.
    if ((l = PyList_New(sipCpp->size())) == NULL) {
        return NULL;
    }

    int i = 0;
    for(std::list<TYPE *>::iterator iter = sipCpp->begin(); iter != sipCpp->end(); iter++) {
        TYPE *cpp = *iter;
        PyObject *pobj;

        // Get the Python wrapper for the Type instance, creating a new
        // one if necessary, and handle any ownership transfer.
        if ((pobj = sipConvertFromType(cpp, kpTypeDef, sipTransferObj)) == NULL) {
            // There was an error so garbage collect the Python list.
            Py_XDECREF(l);
            return NULL;
        }

        // Add the wrapper to the list.
        PyList_SET_ITEM(l, i++, pobj);
    }

    // Return the Python list.
    return l;
%End

%ConvertToTypeCode
    const sipTypeDef* kpTypeDef = sipFindType("TYPE");

    if (!kpTypeDef) {
        return 0;
    }

    // Check if type is compatible
    if (sipIsErr == NULL) {
        if (!PyList_Check(sipPy)) {
            return 0;
        }
        for (Py_ssize_t i = 0; i < PyList_GET_SIZE(sipPy); ++i) {
            PyObject *item = PyList_GET_ITEM(sipPy, i);
            if (!sipCanConvertToType(item, kpTypeDef, SIP_NOT_NONE)) {
                return 0;
            }
        }
        return 1;
    }
    // Convert Python list of TYPE to std::list<TYPE*>
    std::list<TYPE*> *l = new std::list<TYPE*>();

    for (Py_ssize_t i = 0; i < PyList_GET_SIZE(sipPy); ++i) {
        int state;
        PyObject *item = PyList_GET_ITEM(sipPy, i);
        TYPE* p = static_cast<TYPE*>(sipConvertToType(item, kpTypeDef, NULL, SIP_NOT_NONE, &state, sipIsErr));

        if (*sipIsErr) {
            sipReleaseType(p, kpTypeDef, state);
            delete l;
            return 0;
        }

        sipTransferTo(item, item);
        l->push_back(p);

        sipReleaseType(p, kpTypeDef, state);
    }

    *sipCppPtr = l;
    return sipGetState(sipTransferObj);
%End
};

std_list.h 文件

#include <list>

struct TestStruct {

    int test1{};
    int test2{};

    void printStruct() const;
    TestStruct() = default;
};

typedef std::list<TestStruct*> ListTestStruct;

struct StructContainerLvl2 {
    ListTestStruct listTestStruct;
    StructContainerLvl2() = default;
};

測試.py 文件

import std_list

if __name__ == '__main__':

    testStruct1 = std_list.TestStruct()
    testStruct1.test1 = 1
    testStruct1.test2 = 2

    testStruct2 = std_list.TestStruct()
    testStruct2.test1 = 21
    testStruct2.test2 = 22

    temp_structContainerLvl2 = std_list.StructContainerLvl2()

    print(temp_structContainerLvl2.listTestStruct)

    temp_structContainerLvl2.listTestStruct.append(testStruct1)
    temp_structContainerLvl2.listTestStruct.append(testStruct2)

    print(temp_structContainerLvl2.listTestStruct)

    for item in temp_structContainerLvl2.listTestStruct:
        print("List item {}".format(item))
        print()

問題是列表總是空的。 無論我嘗試在其中存儲什么。 錯誤可能在 type_list.sip 文件中。 我更新了我找到的一個例子,但我不確定它是否正確。

有人可以幫忙嗎?

謝謝約翰尼

問題不在 type_list.sip 文件中,而在 test.py 文件中。

cmd 將某些內容附加到已翻譯的 python 列表中,其中 append 類似...

temp_structContainerLvl2.listTestStruct.append(testStruct1)

不能用於 python 列表的 sip 轉換。

作為一種解決方法,可以使用

temp_structContainerLvl2.listTestStruct = [testStruct1, testStruct2]

temp_structContainerLvl2.listTestStruct += [testStruct3]

我想它不是那么有效,但我現在所擁有的一切。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM