support unordered set/map data structures (fixes #100)

This commit is contained in:
Wenzel Jakob 2016-02-13 00:20:21 +01:00
parent 4fee179900
commit 0880294924
2 changed files with 131 additions and 113 deletions

View File

@ -222,45 +222,49 @@ The following basic data types are supported out of the box (some may require
an additional extension header to be included). To pass other data structures an additional extension header to be included). To pass other data structures
as arguments and return values, refer to the section on binding :ref:`classes`. as arguments and return values, refer to the section on binding :ref:`classes`.
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| Data type | Description | Header file | | Data type | Description | Header file |
+========================+==========================+=======================+ +============================+==========================+=======================+
| int8_t, uint8_t | 8-bit integers | pybind11/pybind11.h | | int8_t, uint8_t | 8-bit integers | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| int16_t, uint16_t | 16-bit integers | pybind11/pybind11.h | | int16_t, uint16_t | 16-bit integers | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| int32_t, uint32_t | 32-bit integers | pybind11/pybind11.h | | int32_t, uint32_t | 32-bit integers | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| int64_t, uint64_t | 64-bit integers | pybind11/pybind11.h | | int64_t, uint64_t | 64-bit integers | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| ssize_t, size_t | Platform-dependent size | pybind11/pybind11.h | | ssize_t, size_t | Platform-dependent size | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| float, double | Floating point types | pybind11/pybind11.h | | float, double | Floating point types | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| bool | Two-state Boolean type | pybind11/pybind11.h | | bool | Two-state Boolean type | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| char | Character literal | pybind11/pybind11.h | | char | Character literal | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| const char * | UTF-8 string literal | pybind11/pybind11.h | | const char * | UTF-8 string literal | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| std::string | STL dynamic UTF-8 string | pybind11/pybind11.h | | std::string | STL dynamic UTF-8 string | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| std::pair<T1, T2> | Pair of two custom types | pybind11/pybind11.h | | std::pair<T1, T2> | Pair of two custom types | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| std::tuple<....> | Arbitrary tuple of types | pybind11/pybind11.h | | std::tuple<....> | Arbitrary tuple of types | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| std::complex<T> | Complex numbers | pybind11/complex.h | | std::complex<T> | Complex numbers | pybind11/complex.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| std::array<T, Size> | STL static array | pybind11/stl.h | | std::array<T, Size> | STL static array | pybind11/stl.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| std::vector<T> | STL dynamic array | pybind11/stl.h | | std::vector<T> | STL dynamic array | pybind11/stl.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| std::map<T1, T2> | STL ordered map | pybind11/stl.h | | std::map<T1, T2> | STL ordered map | pybind11/stl.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| std::unordered_map<T1, T2> | STL unordered map | pybind11/stl.h |
+----------------------------+--------------------------+-----------------------+
| std::set<T> | STL ordered set | pybind11/stl.h | | std::set<T> | STL ordered set | pybind11/stl.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
| std::unordered_set<T> | STL unordered set | pybind11/stl.h |
+----------------------------+--------------------------+-----------------------+
| std::function<...> | STL polymorphic function | pybind11/functional.h | | std::function<...> | STL polymorphic function | pybind11/functional.h |
+------------------------+--------------------------+-----------------------+ +----------------------------+--------------------------+-----------------------+
.. [#f1] In practice, implementation and binding code will generally be located .. [#f1] In practice, implementation and binding code will generally be located

View File

@ -10,8 +10,10 @@
#pragma once #pragma once
#include "pybind11.h" #include "pybind11.h"
#include <map>
#include <set> #include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <iostream> #include <iostream>
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -22,77 +24,10 @@
NAMESPACE_BEGIN(pybind11) NAMESPACE_BEGIN(pybind11)
NAMESPACE_BEGIN(detail) NAMESPACE_BEGIN(detail)
template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>> { template <typename Type, typename Key> struct set_caster {
typedef std::vector<Type, Alloc> vector_type; typedef Type type;
typedef type_caster<Type> value_conv;
public:
bool load(handle src, bool convert) {
list l(src, true);
if (!l.check())
return false;
value.reserve(l.size());
value.clear();
value_conv conv;
for (auto it : l) {
if (!conv.load(it, convert))
return false;
value.push_back((Type) conv);
}
return true;
}
static handle cast(const vector_type &src, return_value_policy policy, handle parent) {
list l(src.size());
size_t index = 0;
for (auto const &value: src) {
object value_ = object(value_conv::cast(value, policy, parent), false);
if (!value_)
return handle();
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
}
return l.release();
}
PYBIND11_TYPE_CASTER(vector_type, _("list<") + value_conv::name() + _(">"));
};
template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>> {
typedef std::array<Type, Size> array_type;
typedef type_caster<Type> value_conv;
public:
bool load(handle src, bool convert) {
list l(src, true);
if (!l.check())
return false;
if (l.size() != Size)
return false;
value_conv conv;
size_t ctr = 0;
for (auto it : l) {
if (!conv.load(it, convert))
return false;
value[ctr++] = (Type) conv;
}
return true;
}
static handle cast(const array_type &src, return_value_policy policy, handle parent) {
list l(Size);
size_t index = 0;
for (auto const &value: src) {
object value_ = object(value_conv::cast(value, policy, parent), false);
if (!value_)
return handle();
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
}
return l.release();
}
PYBIND11_TYPE_CASTER(array_type, _("list<") + value_conv::name() + _(">") + _("[") + _<Size>() + _("]"));
};
template <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>> {
typedef std::set<Key, Compare, Alloc> type;
typedef type_caster<Key> key_conv; typedef type_caster<Key> key_conv;
public:
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
pybind11::set s(src, true); pybind11::set s(src, true);
if (!s.check()) if (!s.check())
@ -116,12 +51,12 @@ public:
} }
return s.release(); return s.release();
} }
PYBIND11_TYPE_CASTER(type, _("set<") + key_conv::name() + _(">")); PYBIND11_TYPE_CASTER(type, _("set<") + key_conv::name() + _(">"));
}; };
template <typename Key, typename Value, typename Compare, typename Alloc> struct type_caster<std::map<Key, Value, Compare, Alloc>> { template <typename Type, typename Key, typename Value> struct map_caster {
public: typedef Type type;
typedef std::map<Key, Value, Compare, Alloc> type;
typedef type_caster<Key> key_conv; typedef type_caster<Key> key_conv;
typedef type_caster<Value> value_conv; typedef type_caster<Value> value_conv;
@ -156,6 +91,85 @@ public:
PYBIND11_TYPE_CASTER(type, _("dict<") + key_conv::name() + _(", ") + value_conv::name() + _(">")); PYBIND11_TYPE_CASTER(type, _("dict<") + key_conv::name() + _(", ") + value_conv::name() + _(">"));
}; };
template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>> {
typedef std::vector<Type, Alloc> vector_type;
typedef type_caster<Type> value_conv;
bool load(handle src, bool convert) {
list l(src, true);
if (!l.check())
return false;
value.reserve(l.size());
value.clear();
value_conv conv;
for (auto it : l) {
if (!conv.load(it, convert))
return false;
value.push_back((Type) conv);
}
return true;
}
static handle cast(const vector_type &src, return_value_policy policy, handle parent) {
list l(src.size());
size_t index = 0;
for (auto const &value: src) {
object value_ = object(value_conv::cast(value, policy, parent), false);
if (!value_)
return handle();
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
}
return l.release();
}
PYBIND11_TYPE_CASTER(vector_type, _("list<") + value_conv::name() + _(">"));
};
template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>> {
typedef std::array<Type, Size> array_type;
typedef type_caster<Type> value_conv;
bool load(handle src, bool convert) {
list l(src, true);
if (!l.check())
return false;
if (l.size() != Size)
return false;
value_conv conv;
size_t ctr = 0;
for (auto it : l) {
if (!conv.load(it, convert))
return false;
value[ctr++] = (Type) conv;
}
return true;
}
static handle cast(const array_type &src, return_value_policy policy, handle parent) {
list l(Size);
size_t index = 0;
for (auto const &value: src) {
object value_ = object(value_conv::cast(value, policy, parent), false);
if (!value_)
return handle();
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
}
return l.release();
}
PYBIND11_TYPE_CASTER(array_type, _("list<") + value_conv::name() + _(">") + _("[") + _<Size>() + _("]"));
};
template <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>>
: set_caster<std::set<Key, Compare, Alloc>, Key> { };
template <typename Key, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>>
: set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> { };
template <typename Key, typename Value, typename Compare, typename Alloc> struct type_caster<std::map<Key, Value, Compare, Alloc>>
: map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> { };
template <typename Key, typename Value, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>>
: map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> { };
NAMESPACE_END(detail) NAMESPACE_END(detail)
inline std::ostream &operator<<(std::ostream &os, const handle &obj) { inline std::ostream &operator<<(std::ostream &os, const handle &obj) {