Commit 08802949 by Wenzel Jakob

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

parent 4fee1799
...@@ -222,45 +222,49 @@ The following basic data types are supported out of the box (some may require ...@@ -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
......
...@@ -10,8 +10,10 @@ ...@@ -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,10 +24,77 @@ ...@@ -22,10 +24,77 @@
NAMESPACE_BEGIN(pybind11) NAMESPACE_BEGIN(pybind11)
NAMESPACE_BEGIN(detail) NAMESPACE_BEGIN(detail)
template <typename Type, typename Key> struct set_caster {
typedef Type type;
typedef type_caster<Key> key_conv;
bool load(handle src, bool convert) {
pybind11::set s(src, true);
if (!s.check())
return false;
value.clear();
key_conv conv;
for (auto entry : s) {
if (!conv.load(entry, convert))
return false;
value.insert((Key) conv);
}
return true;
}
static handle cast(const type &src, return_value_policy policy, handle parent) {
pybind11::set s;
for (auto const &value: src) {
object value_ = object(key_conv::cast(value, policy, parent), false);
if (!value_ || !s.add(value_))
return handle();
}
return s.release();
}
PYBIND11_TYPE_CASTER(type, _("set<") + key_conv::name() + _(">"));
};
template <typename Type, typename Key, typename Value> struct map_caster {
typedef Type type;
typedef type_caster<Key> key_conv;
typedef type_caster<Value> value_conv;
bool load(handle src, bool convert) {
dict d(src, true);
if (!d.check())
return false;
key_conv kconv;
value_conv vconv;
value.clear();
for (auto it : d) {
if (!kconv.load(it.first.ptr(), convert) ||
!vconv.load(it.second.ptr(), convert))
return false;
value[(Key) kconv] = (Value) vconv;
}
return true;
}
static handle cast(const type &src, return_value_policy policy, handle parent) {
dict d;
for (auto const &kv: src) {
object key = object(key_conv::cast(kv.first, policy, parent), false);
object value = object(value_conv::cast(kv.second, policy, parent), false);
if (!key || !value)
return handle();
d[key] = value;
}
return d.release();
}
PYBIND11_TYPE_CASTER(type, _("dict<") + key_conv::name() + _(", ") + value_conv::name() + _(">"));
};
template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>> { template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>> {
typedef std::vector<Type, Alloc> vector_type; typedef std::vector<Type, Alloc> vector_type;
typedef type_caster<Type> value_conv; typedef type_caster<Type> value_conv;
public:
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
list l(src, true); list l(src, true);
if (!l.check()) if (!l.check())
...@@ -58,7 +127,7 @@ public: ...@@ -58,7 +127,7 @@ public:
template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>> { template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>> {
typedef std::array<Type, Size> array_type; typedef std::array<Type, Size> array_type;
typedef type_caster<Type> value_conv; typedef type_caster<Type> value_conv;
public:
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
list l(src, true); list l(src, true);
if (!l.check()) if (!l.check())
...@@ -89,72 +158,17 @@ public: ...@@ -89,72 +158,17 @@ public:
PYBIND11_TYPE_CASTER(array_type, _("list<") + value_conv::name() + _(">") + _("[") + _<Size>() + _("]")); 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>> { template <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>>
typedef std::set<Key, Compare, Alloc> type; : set_caster<std::set<Key, Compare, Alloc>, Key> { };
typedef type_caster<Key> key_conv;
public:
bool load(handle src, bool convert) {
pybind11::set s(src, true);
if (!s.check())
return false;
value.clear();
key_conv conv;
for (auto entry : s) {
if (!conv.load(entry, convert))
return false;
value.insert((Key) conv);
}
return true;
}
static handle cast(const type &src, return_value_policy policy, handle parent) {
pybind11::set s;
for (auto const &value: src) {
object value_ = object(key_conv::cast(value, policy, parent), false);
if (!value_ || !s.add(value_))
return handle();
}
return s.release();
}
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>> {
public:
typedef std::map<Key, Value, Compare, Alloc> type;
typedef type_caster<Key> key_conv;
typedef type_caster<Value> value_conv;
bool load(handle src, bool convert) { template <typename Key, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>>
dict d(src, true); : set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> { };
if (!d.check())
return false;
key_conv kconv;
value_conv vconv;
value.clear();
for (auto it : d) {
if (!kconv.load(it.first.ptr(), convert) ||
!vconv.load(it.second.ptr(), convert))
return false;
value[(Key) kconv] = (Value) vconv;
}
return true;
}
static handle cast(const type &src, return_value_policy policy, handle parent) { template <typename Key, typename Value, typename Compare, typename Alloc> struct type_caster<std::map<Key, Value, Compare, Alloc>>
dict d; : map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> { };
for (auto const &kv: src) {
object key = object(key_conv::cast(kv.first, policy, parent), false);
object value = object(value_conv::cast(kv.second, policy, parent), false);
if (!key || !value)
return handle();
d[key] = value;
}
return d.release();
}
PYBIND11_TYPE_CASTER(type, _("dict<") + key_conv::name() + _(", ") + value_conv::name() + _(">")); 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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment