mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-11 08:03:55 +00:00
Accept any sequence type as std::vector (or std::list)
This commit is contained in:
parent
26df852392
commit
d2afe7f001
@ -29,12 +29,14 @@ namespace accessor_policies {
|
||||
struct obj_attr;
|
||||
struct str_attr;
|
||||
struct generic_item;
|
||||
struct sequence_item;
|
||||
struct list_item;
|
||||
struct tuple_item;
|
||||
}
|
||||
using obj_attr_accessor = accessor<accessor_policies::obj_attr>;
|
||||
using str_attr_accessor = accessor<accessor_policies::str_attr>;
|
||||
using item_accessor = accessor<accessor_policies::generic_item>;
|
||||
using sequence_accessor = accessor<accessor_policies::sequence_item>;
|
||||
using list_accessor = accessor<accessor_policies::list_item>;
|
||||
using tuple_accessor = accessor<accessor_policies::tuple_item>;
|
||||
|
||||
@ -261,6 +263,23 @@ struct generic_item {
|
||||
}
|
||||
};
|
||||
|
||||
struct sequence_item {
|
||||
using key_type = size_t;
|
||||
|
||||
static object get(handle obj, size_t index) {
|
||||
PyObject *result = PySequence_GetItem(obj.ptr(), static_cast<ssize_t>(index));
|
||||
if (!result) { throw error_already_set(); }
|
||||
return {result, true};
|
||||
}
|
||||
|
||||
static void set(handle obj, size_t index, handle val) {
|
||||
// PySequence_SetItem does not steal a reference to 'val'
|
||||
if (PySequence_SetItem(obj.ptr(), static_cast<ssize_t>(index), val.ptr()) != 0) {
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct list_item {
|
||||
using key_type = size_t;
|
||||
|
||||
@ -673,6 +692,13 @@ public:
|
||||
bool contains(const char *key) const { return PyDict_Contains(ptr(), pybind11::str(key).ptr()) == 1; }
|
||||
};
|
||||
|
||||
class sequence : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT(sequence, object, PySequence_Check)
|
||||
size_t size() const { return (size_t) PySequence_Size(m_ptr); }
|
||||
detail::sequence_accessor operator[](size_t index) const { return {*this, index}; }
|
||||
};
|
||||
|
||||
class list : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT(list, object, PyList_Check)
|
||||
|
@ -97,13 +97,13 @@ template <typename Type, typename Value> struct list_caster {
|
||||
using value_conv = make_caster<Value>;
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
list l(src, true);
|
||||
if (!l.check())
|
||||
sequence s(src, true);
|
||||
if (!s.check())
|
||||
return false;
|
||||
value_conv conv;
|
||||
value.clear();
|
||||
reserve_maybe(l, &value);
|
||||
for (auto it : l) {
|
||||
reserve_maybe(s, &value);
|
||||
for (auto it : s) {
|
||||
if (!conv.load(it, convert))
|
||||
return false;
|
||||
value.push_back((Value) conv);
|
||||
@ -113,8 +113,8 @@ template <typename Type, typename Value> struct list_caster {
|
||||
|
||||
template <typename T = Type,
|
||||
enable_if_t<std::is_same<decltype(std::declval<T>().reserve(0)), void>::value, int> = 0>
|
||||
void reserve_maybe(list l, Type *) { value.reserve(l.size()); }
|
||||
void reserve_maybe(list, void *) { }
|
||||
void reserve_maybe(sequence s, Type *) { value.reserve(s.size()); }
|
||||
void reserve_maybe(sequence, void *) { }
|
||||
|
||||
static handle cast(const Type &src, return_value_policy policy, handle parent) {
|
||||
list l(src.size());
|
||||
|
@ -71,6 +71,14 @@ def test_instance(capture):
|
||||
list item 0: value
|
||||
list item 1: value2
|
||||
"""
|
||||
with capture:
|
||||
list_result = instance.get_list_2()
|
||||
list_result.append('value2')
|
||||
instance.print_list_2(tuple(list_result))
|
||||
assert capture.unordered == """
|
||||
list item 0: value
|
||||
list item 1: value2
|
||||
"""
|
||||
array_result = instance.get_array()
|
||||
assert array_result == ['array entry 1', 'array entry 2']
|
||||
with capture:
|
||||
|
Loading…
Reference in New Issue
Block a user