Skip to content

Commit 9537d8f

Browse files
authored
Merge pull request #502 from jcarpent/topic/type_info
Add helper for type_info
2 parents 52092f6 + 6552b9a commit 9537d8f

File tree

8 files changed

+195
-0
lines changed

8 files changed

+195
-0
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66

77
## [Unreleased]
88

9+
### Added
10+
- Add type_info helpers ([#502](https://github.com/stack-of-tasks/eigenpy/pull/502))
11+
912
## [3.9.0] - 2024-08-31
1013

1114
### Changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ set(${PROJECT_NAME}_HEADERS
275275
include/eigenpy/variant.hpp
276276
include/eigenpy/std-unique-ptr.hpp
277277
include/eigenpy/swig.hpp
278+
include/eigenpy/type_info.hpp
278279
include/eigenpy/version.hpp)
279280

280281
list(
@@ -349,6 +350,7 @@ set(${PROJECT_NAME}_SOURCES
349350
src/scipy-type.cpp
350351
src/std-vector.cpp
351352
src/optional.cpp
353+
src/type_info.cpp
352354
src/version.cpp)
353355

354356
add_library(${PROJECT_NAME} SHARED ${${PROJECT_NAME}_SOURCES}

include/eigenpy/type_info.hpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
///
2+
/// Copyright (c) 2024 INRIA
3+
///
4+
5+
#ifndef __eigenpy_type_info_hpp__
6+
#define __eigenpy_type_info_hpp__
7+
8+
#include "eigenpy/fwd.hpp"
9+
10+
#include <boost/type_index.hpp>
11+
#include <typeinfo>
12+
#include <typeindex>
13+
14+
namespace eigenpy {
15+
16+
template <typename T>
17+
boost::typeindex::type_index type_info(const T& value) {
18+
return boost::typeindex::type_id_runtime(value);
19+
}
20+
21+
template <typename T>
22+
void expose_boost_type_info() {
23+
boost::python::def(
24+
"type_info",
25+
+[](const T& value) -> boost::typeindex::type_index {
26+
return boost::typeindex::type_id_runtime(value);
27+
},
28+
bp::arg("value"),
29+
"Returns information of the type of value as a "
30+
"boost::typeindex::type_index (can work without RTTI).");
31+
boost::python::def(
32+
"boost_type_info",
33+
+[](const T& value) -> boost::typeindex::type_index {
34+
return boost::typeindex::type_id_runtime(value);
35+
},
36+
bp::arg("value"),
37+
"Returns information of the type of value as a "
38+
"boost::typeindex::type_index (can work without RTTI).");
39+
}
40+
41+
template <typename T>
42+
void expose_std_type_info() {
43+
boost::python::def(
44+
"std_type_info",
45+
+[](const T& value) -> std::type_index { return typeid(value); },
46+
bp::arg("value"),
47+
"Returns information of the type of value as a std::type_index.");
48+
}
49+
50+
///
51+
/// \brief Add the Python method type_info to query information of a type.
52+
///
53+
template <class C>
54+
struct TypeInfoVisitor : public bp::def_visitor<TypeInfoVisitor<C> > {
55+
template <class PyClass>
56+
void visit(PyClass& cl) const {
57+
cl.def("type_info", &boost_type_info, bp::arg("self"),
58+
"Queries information of the type of *this as a "
59+
"boost::typeindex::type_index (can work without RTTI).");
60+
cl.def("boost_type_info", &boost_type_info, bp::arg("self"),
61+
"Queries information of the type of *this as a "
62+
"boost::typeindex::type_index (can work without RTTI).");
63+
cl.def("std_type_info", &std_type_info, bp::arg("self"),
64+
"Queries information of the type of *this as a std::type_index.");
65+
}
66+
67+
private:
68+
static boost::typeindex::type_index boost_type_info(const C& self) {
69+
return boost::typeindex::type_id_runtime(self);
70+
}
71+
72+
static std::type_index std_type_info(const C& self) { return typeid(self); }
73+
};
74+
75+
} // namespace eigenpy
76+
77+
#endif // __eigenpy_type_info_hpp__

src/eigenpy.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ void exposeMatrixComplexDouble();
3636
void exposeMatrixComplexLongDouble();
3737

3838
void exposeNoneType();
39+
void exposeTypeInfo();
3940

4041
/* Enable Eigen-Numpy serialization for a set of standard MatrixBase instances.
4142
*/
@@ -84,6 +85,7 @@ void enableEigenPy() {
8485
exposeMatrixComplexLongDouble();
8586

8687
exposeNoneType();
88+
exposeTypeInfo();
8789
}
8890

8991
bool withTensorSupport() {

src/type_info.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
///
2+
/// Copyright 2024 INRIA
3+
///
4+
5+
#include <typeinfo>
6+
#include <typeindex>
7+
8+
#include <boost/python.hpp>
9+
#include <boost/type_index.hpp>
10+
11+
#include "eigenpy/registration.hpp"
12+
13+
namespace bp = boost::python;
14+
15+
namespace eigenpy {
16+
17+
void exposeStdTypeIndex() {
18+
typedef std::type_index Self;
19+
if (register_symbolic_link_to_registered_type<Self>()) return;
20+
21+
bp::class_<Self>(
22+
"std_type_index",
23+
"The class type_index holds implementation-specific information about a "
24+
"type, including the name of the type and means to compare two types for "
25+
"equality or collating order.",
26+
bp::no_init)
27+
.def(bp::self == bp::self)
28+
.def(bp::self >= bp::self)
29+
.def(bp::self > bp::self)
30+
.def(bp::self < bp::self)
31+
.def(bp::self <= bp::self)
32+
.def("hash_code", &Self::hash_code, bp::arg("self"),
33+
"Returns an unspecified value (here denoted by hash code) such that "
34+
"for all std::type_info objects referring to the same type, their "
35+
"hash code is the same.")
36+
.def("name", &Self::name, bp::arg("self"),
37+
"Returns an implementation defined null-terminated character string "
38+
"containing the name of the type. No guarantees are given; in "
39+
"particular, the returned string can be identical for several types "
40+
"and change between invocations of the same program.")
41+
.def(
42+
"pretty_name",
43+
+[](const Self &value) -> std::string {
44+
return boost::core::demangle(value.name());
45+
},
46+
bp::arg("self"), "Human readible name.");
47+
}
48+
49+
void exposeBoostTypeIndex() {
50+
typedef boost::typeindex::type_index Self;
51+
if (register_symbolic_link_to_registered_type<Self>()) return;
52+
53+
bp::class_<Self>(
54+
"boost_type_index",
55+
"The class type_index holds implementation-specific information about a "
56+
"type, including the name of the type and means to compare two types for "
57+
"equality or collating order.",
58+
bp::no_init)
59+
.def(bp::self == bp::self)
60+
.def(bp::self >= bp::self)
61+
.def(bp::self > bp::self)
62+
.def(bp::self < bp::self)
63+
.def(bp::self <= bp::self)
64+
.def("hash_code", &Self::hash_code, bp::arg("self"),
65+
"Returns an unspecified value (here denoted by hash code) such that "
66+
"for all std::type_info objects referring to the same type, their "
67+
"hash code is the same.")
68+
.def("name", &Self::name, bp::arg("self"),
69+
"Returns an implementation defined null-terminated character string "
70+
"containing the name of the type. No guarantees are given; in "
71+
"particular, the returned string can be identical for several types "
72+
"and change between invocations of the same program.")
73+
.def("pretty_name", &Self::pretty_name, bp::arg("self"),
74+
"Human readible name.");
75+
}
76+
77+
void exposeTypeInfo() {
78+
exposeStdTypeIndex();
79+
exposeBoostTypeIndex();
80+
}
81+
} // namespace eigenpy

unittest/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ endfunction()
3535

3636
add_dependencies(build_tests ${PYWRAP})
3737
add_lib_unit_test(matrix)
38+
add_lib_unit_test(type_info)
3839
add_lib_unit_test(multiple_registration)
3940
if(BUILD_TESTING_SCIPY)
4041
find_scipy()
@@ -111,6 +112,7 @@ endif()
111112
add_lib_unit_test(bind_virtual_factory)
112113

113114
add_python_lib_unit_test("py-matrix" "unittest/python/test_matrix.py")
115+
add_python_lib_unit_test("py-type-info" "unittest/python/test_type_info.py")
114116
add_python_lib_unit_test("py-multiple-registration"
115117
"unittest/python/test_multiple_registration.py")
116118

unittest/python/test_type_info.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import type_info
2+
3+
d = type_info.Dummy()
4+
assert "Dummy" in d.type_info().pretty_name()
5+
6+
assert type_info.type_info(1).pretty_name() == "int"
7+
assert "basic_string" in type_info.type_info("toto").pretty_name()

unittest/type_info.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright 2024 INRIA
3+
*/
4+
5+
#include <iostream>
6+
7+
#include "eigenpy/eigenpy.hpp"
8+
#include "eigenpy/type_info.hpp"
9+
10+
struct Dummy {};
11+
12+
BOOST_PYTHON_MODULE(type_info) {
13+
using namespace Eigen;
14+
namespace bp = boost::python;
15+
eigenpy::enableEigenPy();
16+
17+
eigenpy::expose_boost_type_info<int>();
18+
eigenpy::expose_boost_type_info<std::string>();
19+
20+
bp::class_<Dummy>("Dummy").def(eigenpy::TypeInfoVisitor<Dummy>());
21+
}

0 commit comments

Comments
 (0)