如何使用 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.
在 std::list 中自定义结构指针(我也用 sip 翻译的结构)
我构建了一个小例子来说明我的情况:
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;
};
test.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 文件中。
将某些内容附加到已翻译的 python 列表中的 cmd,其附加方式类似于 ...
temp_structContainerLvl2.listTestStruct.append(testStruct1)
不能用于 python 列表的 sip 翻译。
作为一种解决方法,可以使用
temp_structContainerLvl2.listTestStruct = [testStruct1, testStruct2]
和
temp_structContainerLvl2.listTestStruct += [testStruct3]
我想它不是那么有效,但我现在已经有了。
我正在使用带有 python 3.8 的 SIP 版本 6.0.1 并且有给定的 c++11 API。 (在 Ubuntu 18.04)
目标是存储例如使用 python.
在 std::list 中自定义结构指针(我也用 sip 翻译的结构)我构建了一个小例子来说明我的情况:
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;
};
test.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 文件中。
将某些内容附加到已翻译的 python 列表中的 cmd,其附加方式类似于 ...
temp_structContainerLvl2.listTestStruct.append(testStruct1)
不能用于 python 列表的 sip 翻译。
作为一种解决方法,可以使用
temp_structContainerLvl2.listTestStruct = [testStruct1, testStruct2]
和
temp_structContainerLvl2.listTestStruct += [testStruct3]
我想它不是那么有效,但我现在已经有了。