Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [Unreleased]

### Added
- Add type_info helpers ([#502](https://github.com/stack-of-tasks/eigenpy/pull/502))

## [3.9.0] - 2024-08-31

### Changed
Expand Down
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ set(${PROJECT_NAME}_HEADERS
include/eigenpy/variant.hpp
include/eigenpy/std-unique-ptr.hpp
include/eigenpy/swig.hpp
include/eigenpy/type_info.hpp
include/eigenpy/version.hpp)

list(
Expand Down Expand Up @@ -349,6 +350,7 @@ set(${PROJECT_NAME}_SOURCES
src/scipy-type.cpp
src/std-vector.cpp
src/optional.cpp
src/type_info.cpp
src/version.cpp)

add_library(${PROJECT_NAME} SHARED ${${PROJECT_NAME}_SOURCES}
Expand Down
77 changes: 77 additions & 0 deletions include/eigenpy/type_info.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
///
/// Copyright (c) 2024 INRIA
///

#ifndef __eigenpy_type_info_hpp__
#define __eigenpy_type_info_hpp__

#include "eigenpy/fwd.hpp"

#include <boost/type_index.hpp>
#include <typeinfo>
#include <typeindex>

namespace eigenpy {

template <typename T>
boost::typeindex::type_index type_info(const T& value) {
return boost::typeindex::type_id_runtime(value);
}

template <typename T>
void expose_boost_type_info() {
boost::python::def(
"type_info",
+[](const T& value) -> boost::typeindex::type_index {
return boost::typeindex::type_id_runtime(value);
},
bp::arg("value"),
"Returns information of the type of value as a "
"boost::typeindex::type_index (can work without RTTI).");
boost::python::def(
"boost_type_info",
+[](const T& value) -> boost::typeindex::type_index {
return boost::typeindex::type_id_runtime(value);
},
bp::arg("value"),
"Returns information of the type of value as a "
"boost::typeindex::type_index (can work without RTTI).");
}

template <typename T>
void expose_std_type_info() {
boost::python::def(
"std_type_info",
+[](const T& value) -> std::type_index { return typeid(value); },
bp::arg("value"),
"Returns information of the type of value as a std::type_index.");
}

///
/// \brief Add the Python method type_info to query information of a type.
///
template <class C>
struct TypeInfoVisitor : public bp::def_visitor<TypeInfoVisitor<C> > {
template <class PyClass>
void visit(PyClass& cl) const {
cl.def("type_info", &boost_type_info, bp::arg("self"),
"Queries information of the type of *this as a "
"boost::typeindex::type_index (can work without RTTI).");
cl.def("boost_type_info", &boost_type_info, bp::arg("self"),
"Queries information of the type of *this as a "
"boost::typeindex::type_index (can work without RTTI).");
cl.def("std_type_info", &std_type_info, bp::arg("self"),
"Queries information of the type of *this as a std::type_index.");
}

private:
static boost::typeindex::type_index boost_type_info(const C& self) {
return boost::typeindex::type_id_runtime(self);
}

static std::type_index std_type_info(const C& self) { return typeid(self); }
};

} // namespace eigenpy

#endif // __eigenpy_type_info_hpp__
2 changes: 2 additions & 0 deletions src/eigenpy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ void exposeMatrixComplexDouble();
void exposeMatrixComplexLongDouble();

void exposeNoneType();
void exposeTypeInfo();

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

exposeNoneType();
exposeTypeInfo();
}

bool withTensorSupport() {
Expand Down
81 changes: 81 additions & 0 deletions src/type_info.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
///
/// Copyright 2024 INRIA
///

#include <typeinfo>
#include <typeindex>

#include <boost/python.hpp>
#include <boost/type_index.hpp>

#include "eigenpy/registration.hpp"

namespace bp = boost::python;

namespace eigenpy {

void exposeStdTypeIndex() {
typedef std::type_index Self;
if (register_symbolic_link_to_registered_type<Self>()) return;

bp::class_<Self>(
"std_type_index",
"The class type_index holds implementation-specific information about a "
"type, including the name of the type and means to compare two types for "
"equality or collating order.",
bp::no_init)
.def(bp::self == bp::self)
.def(bp::self >= bp::self)
.def(bp::self > bp::self)
.def(bp::self < bp::self)
.def(bp::self <= bp::self)
.def("hash_code", &Self::hash_code, bp::arg("self"),
"Returns an unspecified value (here denoted by hash code) such that "
"for all std::type_info objects referring to the same type, their "
"hash code is the same.")
.def("name", &Self::name, bp::arg("self"),
"Returns an implementation defined null-terminated character string "
"containing the name of the type. No guarantees are given; in "
"particular, the returned string can be identical for several types "
"and change between invocations of the same program.")
.def(
"pretty_name",
+[](const Self &value) -> std::string {
return boost::core::demangle(value.name());
},
bp::arg("self"), "Human readible name.");
}

void exposeBoostTypeIndex() {
typedef boost::typeindex::type_index Self;
if (register_symbolic_link_to_registered_type<Self>()) return;

bp::class_<Self>(
"boost_type_index",
"The class type_index holds implementation-specific information about a "
"type, including the name of the type and means to compare two types for "
"equality or collating order.",
bp::no_init)
.def(bp::self == bp::self)
.def(bp::self >= bp::self)
.def(bp::self > bp::self)
.def(bp::self < bp::self)
.def(bp::self <= bp::self)
.def("hash_code", &Self::hash_code, bp::arg("self"),
"Returns an unspecified value (here denoted by hash code) such that "
"for all std::type_info objects referring to the same type, their "
"hash code is the same.")
.def("name", &Self::name, bp::arg("self"),
"Returns an implementation defined null-terminated character string "
"containing the name of the type. No guarantees are given; in "
"particular, the returned string can be identical for several types "
"and change between invocations of the same program.")
.def("pretty_name", &Self::pretty_name, bp::arg("self"),
"Human readible name.");
}

void exposeTypeInfo() {
exposeStdTypeIndex();
exposeBoostTypeIndex();
}
} // namespace eigenpy
2 changes: 2 additions & 0 deletions unittest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ endfunction()

add_dependencies(build_tests ${PYWRAP})
add_lib_unit_test(matrix)
add_lib_unit_test(type_info)
add_lib_unit_test(multiple_registration)
if(BUILD_TESTING_SCIPY)
find_scipy()
Expand Down Expand Up @@ -111,6 +112,7 @@ endif()
add_lib_unit_test(bind_virtual_factory)

add_python_lib_unit_test("py-matrix" "unittest/python/test_matrix.py")
add_python_lib_unit_test("py-type-info" "unittest/python/test_type_info.py")
add_python_lib_unit_test("py-multiple-registration"
"unittest/python/test_multiple_registration.py")

Expand Down
7 changes: 7 additions & 0 deletions unittest/python/test_type_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type_info

d = type_info.Dummy()
assert "Dummy" in d.type_info().pretty_name()

assert type_info.type_info(1).pretty_name() == "int"
assert "basic_string" in type_info.type_info("toto").pretty_name()
21 changes: 21 additions & 0 deletions unittest/type_info.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright 2024 INRIA
*/

#include <iostream>

#include "eigenpy/eigenpy.hpp"
#include "eigenpy/type_info.hpp"

struct Dummy {};

BOOST_PYTHON_MODULE(type_info) {
using namespace Eigen;
namespace bp = boost::python;
eigenpy::enableEigenPy();

eigenpy::expose_boost_type_info<int>();
eigenpy::expose_boost_type_info<std::string>();

bp::class_<Dummy>("Dummy").def(eigenpy::TypeInfoVisitor<Dummy>());
}