Commit 08802949 authored by Wenzel Jakob's avatar Wenzel Jakob
Browse files

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
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`.
+------------------------+--------------------------+-----------------------+
| Data type | Description | Header file |
+========================+==========================+=======================+
| int8_t, uint8_t | 8-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 |
+------------------------+--------------------------+-----------------------+
| int64_t, uint64_t | 64-bit integers | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+
| ssize_t, size_t | Platform-dependent size | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+
| float, double | Floating point types | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+
| bool | Two-state Boolean type | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+
| char | Character literal | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+
| const char * | UTF-8 string literal | 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::tuple<....> | Arbitrary tuple of types | pybind11/pybind11.h |
+------------------------+--------------------------+-----------------------+
| std::complex<T> | Complex numbers | pybind11/complex.h |
+------------------------+--------------------------+-----------------------+
| std::array<T, Size> | STL static array | pybind11/stl.h |
+------------------------+--------------------------+-----------------------+
| std::vector<T> | STL dynamic array | pybind11/stl.h |
+------------------------+--------------------------+-----------------------+
| std::map<T1, T2> | STL ordered map | pybind11/stl.h |
+------------------------+--------------------------+-----------------------+
| std::set<T> | STL ordered set | pybind11/stl.h |
+------------------------+--------------------------+-----------------------+
| std::function<...> | STL polymorphic function | pybind11/functional.h |
+------------------------+--------------------------+-----------------------+
+----------------------------+--------------------------+-----------------------+
| Data type | Description | Header file |
+============================+==========================+=======================+
| int8_t, uint8_t | 8-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 |
+----------------------------+--------------------------+-----------------------+
| int64_t, uint64_t | 64-bit integers | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| ssize_t, size_t | Platform-dependent size | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| float, double | Floating point types | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| bool | Two-state Boolean type | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| char | Character literal | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| const char * | UTF-8 string literal | 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::tuple<....> | Arbitrary tuple of types | pybind11/pybind11.h |
+----------------------------+--------------------------+-----------------------+
| std::complex<T> | Complex numbers | pybind11/complex.h |
+----------------------------+--------------------------+-----------------------+
| std::array<T, Size> | STL static array | pybind11/stl.h |
+----------------------------+--------------------------+-----------------------+
| std::vector<T> | STL dynamic array | 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::unordered_set<T> | STL unordered set | pybind11/stl.h |
+----------------------------+--------------------------+-----------------------+
| std::function<...> | STL polymorphic function | pybind11/functional.h |
+----------------------------+--------------------------+-----------------------+
.. [#f1] In practice, implementation and binding code will generally be located
......
......@@ -10,8 +10,10 @@
#pragma once
#include "pybind11.h"
#include <map>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <iostream>
#if defined(_MSC_VER)
......@@ -22,10 +24,77 @@
NAMESPACE_BEGIN(pybind11)
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>> {
typedef std::vector<Type, Alloc> vector_type;
typedef type_caster<Type> value_conv;
public:
bool load(handle src, bool convert) {
list l(src, true);
if (!l.check())
......@@ -58,7 +127,7 @@ public:
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())
......@@ -89,72 +158,17 @@ public:
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;
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;
template <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>>
: set_caster<std::set<Key, Compare, Alloc>, Key> { };
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;
}
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> { };
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();
}
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> { };
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)
......
Supports Markdown
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