Skip to content

Commit

Permalink
Merge pull request #502 from jcarpent/topic/type_info
Browse files Browse the repository at this point in the history
Add helper for type_info
  • Loading branch information
jcarpent authored Sep 3, 2024
2 parents 52092f6 + 6552b9a commit 9537d8f
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 0 deletions.
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>());
}

0 comments on commit 9537d8f

Please sign in to comment.