Skip to content

Commit 1ab15b4

Browse files
authored
Merge pull request #417 from jcarpent/topic/std-pair
Add support of std::pair
2 parents 0d63d8c + 3d7f588 commit 1ab15b4

File tree

6 files changed

+111
-0
lines changed

6 files changed

+111
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
88

99
### Added
1010
- Support for C++11 `std::array` types ([#412](https://github.com/stack-of-tasks/pull/412))
11+
- Support for `std::pair` types ([#417](https://github.com/stack-of-tasks/pull/417))
1112

1213
## [3.1.4] - 2023-11-27
1314

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ set(${PROJECT_NAME}_HEADERS
164164
include/eigenpy/register.hpp
165165
include/eigenpy/std-array.hpp
166166
include/eigenpy/std-map.hpp
167+
include/eigenpy/std-pair.hpp
167168
include/eigenpy/std-vector.hpp
168169
include/eigenpy/optional.hpp
169170
include/eigenpy/pickle-vector.hpp

include/eigenpy/std-pair.hpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//
2+
// Copyright (c) 2023 INRIA
3+
//
4+
5+
#ifndef __eigenpy_utils_std_pair_hpp__
6+
#define __eigenpy_utils_std_pair_hpp__
7+
8+
#include <boost/python.hpp>
9+
#include <utility>
10+
11+
namespace eigenpy {
12+
13+
template <typename pair_type>
14+
struct StdPairConverter {
15+
typedef typename pair_type::first_type T1;
16+
typedef typename pair_type::second_type T2;
17+
18+
static PyObject* convert(const pair_type& pair) {
19+
return boost::python::incref(
20+
boost::python::make_tuple(pair.first, pair.second).ptr());
21+
}
22+
23+
static void* convertible(PyObject* obj) {
24+
if (!PyTuple_CheckExact(obj)) return 0;
25+
if (PyTuple_Size(obj) != 2) return 0;
26+
{
27+
boost::python::tuple tuple(boost::python::borrowed(obj));
28+
boost::python::extract<T1> elt1(tuple[0]);
29+
if (!elt1.check()) return 0;
30+
boost::python::extract<T2> elt2(tuple[1]);
31+
if (!elt2.check()) return 0;
32+
}
33+
return obj;
34+
}
35+
36+
static void construct(
37+
PyObject* obj,
38+
boost::python::converter::rvalue_from_python_stage1_data* memory) {
39+
boost::python::tuple tuple(boost::python::borrowed(obj));
40+
void* storage =
41+
reinterpret_cast<
42+
boost::python::converter::rvalue_from_python_storage<pair_type>*>(
43+
reinterpret_cast<void*>(memory))
44+
->storage.bytes;
45+
new (storage) pair_type(boost::python::extract<T1>(tuple[0]),
46+
boost::python::extract<T2>(tuple[1]));
47+
memory->convertible = storage;
48+
}
49+
50+
static PyTypeObject const* get_pytype() {
51+
PyTypeObject const* py_type = &PyTuple_Type;
52+
return py_type;
53+
}
54+
55+
static void registration() {
56+
boost::python::converter::registry::push_back(
57+
&convertible, &construct, boost::python::type_id<pair_type>()
58+
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
59+
,
60+
get_pytype
61+
#endif
62+
);
63+
boost::python::to_python_converter<pair_type, StdPairConverter, true>();
64+
}
65+
};
66+
67+
} // namespace eigenpy
68+
69+
#endif // ifndef __eigenpy_utils_std_pair_hpp__

unittest/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ if(NOT NUMPY_WITH_BROKEN_UFUNC_SUPPORT)
3939
endif()
4040
add_lib_unit_test(std_vector)
4141
add_lib_unit_test(std_array)
42+
add_lib_unit_test(std_pair)
4243
add_lib_unit_test(user_struct)
4344

4445
function(config_bind_optional tagname opttype)
@@ -115,6 +116,10 @@ add_python_unit_test("py-std-array" "unittest/python/test_std_array.py"
115116
"python;unittest")
116117
set_tests_properties("py-std-array" PROPERTIES DEPENDS ${PYWRAP})
117118

119+
add_python_unit_test("py-std-pair" "unittest/python/test_std_pair.py"
120+
"unittest")
121+
set_tests_properties("py-std-pair" PROPERTIES DEPENDS ${PYWRAP})
122+
118123
add_python_unit_test("py-user-struct" "unittest/python/test_user_struct.py"
119124
"python;unittest")
120125
set_tests_properties("py-user-struct" PROPERTIES DEPENDS ${PYWRAP})

unittest/python/test_std_pair.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from std_pair import std_pair_to_tuple, copy
2+
3+
t = (1, 2.0)
4+
assert std_pair_to_tuple(t) == t
5+
assert copy(t) == t

unittest/std_pair.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/// @file
2+
/// @copyright Copyright 2023 CNRS INRIA
3+
4+
#include <eigenpy/eigenpy.hpp>
5+
#include <eigenpy/std-pair.hpp>
6+
#include <iostream>
7+
8+
namespace bp = boost::python;
9+
10+
template <typename T1, typename T2>
11+
bp::tuple std_pair_to_tuple(const std::pair<T1, T2>& pair) {
12+
return bp::make_tuple(pair.first, pair.second);
13+
}
14+
15+
template <typename T1, typename T2>
16+
std::pair<T1, T2> copy(const std::pair<T1, T2>& pair) {
17+
return pair;
18+
}
19+
20+
BOOST_PYTHON_MODULE(std_pair) {
21+
using namespace eigenpy;
22+
23+
enableEigenPy();
24+
25+
typedef std::pair<int, double> PairType;
26+
StdPairConverter<PairType>::registration();
27+
28+
bp::def("std_pair_to_tuple", std_pair_to_tuple<int, double>);
29+
bp::def("copy", copy<int, double>);
30+
}

0 commit comments

Comments
 (0)