Skip to content
Snippets Groups Projects
Unverified Commit 06c255ac authored by Justin Carpentier's avatar Justin Carpentier Committed by GitHub
Browse files

Merge pull request #337 from jcarpent/devel

Simplify alignment procedure
parents 21f608d4 1697ac05
No related branches found
No related tags found
No related merge requests found
Pipeline #24374 passed with warnings
Subproject commit 1a6db988dbc0c02679d0566d8f3f50dd0aebc569
Subproject commit 9403226002b930d592ca83b50d3cd714a1c2dc01
......@@ -20,6 +20,15 @@ struct aligned_storage {
};
};
template <class Data>
struct aligned_instance {
PyObject_VAR_HEAD PyObject *dict;
PyObject *weakrefs;
boost::python::instance_holder *objects;
typename aligned_storage<sizeof(Data)>::type storage;
};
} // namespace eigenpy
namespace boost {
......@@ -62,6 +71,19 @@ struct referent_storage<const Eigen::Quaternion<Scalar, Options> &> {
} // namespace python
} // namespace boost
namespace boost {
namespace python {
namespace objects {
// Force alignment of instance with value_holder
template <typename Derived>
struct instance<value_holder<Derived> >
: ::eigenpy::aligned_instance<value_holder<Derived> > {};
} // namespace objects
} // namespace python
} // namespace boost
namespace eigenpy {
template <class T>
......
......@@ -5,6 +5,50 @@
#ifndef __eigenpy_fwd_hpp__
#define __eigenpy_fwd_hpp__
#if defined(__clang__)
#define EIGENPY_CLANG_COMPILER
#elif defined(__GNUC__)
#define EIGENPY_GCC_COMPILER
#elif defined(_MSC_VER)
#define EIGENPY_MSVC_COMPILER
#endif
#define EIGENPY_STRING_LITERAL(string) #string
#define EIGENPY_STRINGIZE(string) EIGENPY_STRING_LITERAL(string)
#define _EIGENPY_PPCAT(A, B) A##B
#define EIGENPY_PPCAT(A, B) _EIGENPY_PPCAT(A, B)
#define EIGENPY_STRINGCAT(A, B) A B
// For more details, visit
// https://stackoverflow.com/questions/171435/portability-of-warning-preprocessor-directive
#if defined(EIGENPY_CLANG_COMPILER) || defined(EIGENPY_GCC_COMPILER)
#define EIGENPY_PRAGMA(x) _Pragma(#x)
#define EIGENPY_PRAGMA_MESSAGE(the_message) \
EIGENPY_PRAGMA(GCC message the_message)
#define EIGENPY_PRAGMA_WARNING(the_message) \
EIGENPY_PRAGMA(GCC warning the_message)
#define EIGENPY_PRAGMA_DEPRECATED(the_message) \
EIGENPY_PRAGMA_WARNING(Deprecated : the_message)
#define EIGENPY_PRAGMA_DEPRECATED_HEADER(old_header, new_header) \
EIGENPY_PRAGMA_WARNING( \
Deprecated header file \
: #old_header has been replaced \
by #new_header.\n Please use #new_header instead of #old_header.)
#elif defined(WIN32)
#define EIGENPY_PRAGMA(x) __pragma(#x)
#define EIGENPY_PRAGMA_MESSAGE(the_message) \
EIGENPY_PRAGMA(message(#the_message))
#define EIGENPY_PRAGMA_WARNING(the_message) \
EIGENPY_PRAGMA(message(EIGENPY_STRINGCAT("WARNING: ", the_message)))
#endif
#define EIGENPY_DEPRECATED_MACRO(macro, the_message) \
EIGENPY_PRAGMA_WARNING( \
EIGENPY_STRINGCAT("this macro is deprecated: ", the_message))
#define EIGENPY_DEPRECATED_FILE(the_message) \
EIGENPY_PRAGMA_WARNING( \
EIGENPY_STRINGCAT("this file is deprecated: ", the_message))
#include "eigenpy/config.hpp"
// Silence a warning about a deprecated use of boost bind by boost python
......
/*
* Copyright 2014-2019, CNRS
* Copyright 2018-2022, INRIA
* Copyright 2018-2023, INRIA
*/
#ifndef __eigenpy_memory_hpp__
#define __eigenpy_memory_hpp__
#include "eigenpy/fwd.hpp"
#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE)
static inline void _Py_SET_SIZE(PyVarObject* ob, Py_ssize_t size) {
ob->ob_size = size;
}
#define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size)
#endif
EIGENPY_DEPRECATED_FILE(
"This header file is now useless and should not be included anymore.")
#ifndef __eigenpy_memory_hpp__
#define __eigenpy_memory_hpp__
/**
* This section contains a convenience MACRO which allows an easy specialization
* of Boost Python Object allocator for struct data types containing Eigen
* objects and requiring strict alignment.
*
* This code was proposed as an stackoverflow answer:
* http://stackoverflow.com/questions/13177573/how-to-expose-aligned-class-with-boost-python/29694518
* Leading to this page proposing the solution:
* http://fhtagn.net/prog/2015/04/16/quaternion_boost_python.html
*
*/
#define EIGENPY_DEFINE_STRUCT_ALLOCATOR_SPECIALIZATION(...) \
namespace boost { \
namespace python { \
namespace objects { \
template <> \
struct instance<value_holder<__VA_ARGS__> > { \
typedef value_holder<__VA_ARGS__> Data; \
PyObject_VAR_HEAD PyObject* dict; \
PyObject* weakrefs; \
instance_holder* objects; \
\
typedef type_with_alignment< ::boost::alignment_of<Data>::value>::type \
align_t; \
\
union { \
align_t align; \
char bytes[sizeof(Data) + EIGENPY_DEFAULT_ALIGN_BYTES]; \
} storage; \
}; \
\
template <class Derived> \
struct make_instance_impl<__VA_ARGS__, value_holder<__VA_ARGS__>, Derived> { \
typedef __VA_ARGS__ T; \
typedef value_holder<__VA_ARGS__> Holder; \
typedef objects::instance<Holder> instance_t; \
\
template <class Arg> \
static inline PyObject* execute(Arg& x) { \
BOOST_MPL_ASSERT((mpl::or_<is_class<T>, is_union<T> >)); \
\
PyTypeObject* type = Derived::get_class_object(x); \
\
if (type == 0) return python::detail::none(); \
\
PyObject* raw_result = type->tp_alloc( \
type, objects::additional_instance_size<Holder>::value); \
if (raw_result != 0) { \
python::detail::decref_guard protect(raw_result); \
instance_t* instance = (instance_t*)(void*)raw_result; \
Holder* holder = \
Derived::construct(&instance->storage, (PyObject*)instance, x); \
holder->install(raw_result); \
\
Py_ssize_t holder_offset = \
reinterpret_cast<Py_ssize_t>(holder) - \
reinterpret_cast<Py_ssize_t>(&instance->storage) + \
static_cast<Py_ssize_t>(offsetof(instance_t, storage)); \
Py_SET_SIZE(instance, holder_offset); \
\
protect.cancel(); \
} \
return raw_result; \
} \
}; \
\
template <> \
struct make_instance<__VA_ARGS__, value_holder<__VA_ARGS__> > \
: make_instance_impl< \
__VA_ARGS__, value_holder<__VA_ARGS__>, \
make_instance<__VA_ARGS__, value_holder<__VA_ARGS__> > > { \
template <class U> \
static inline PyTypeObject* get_class_object(U&) { \
return converter::registered<__VA_ARGS__>::converters \
.get_class_object(); \
} \
\
static inline value_holder<__VA_ARGS__>* construct( \
void* storage, PyObject* instance, \
reference_wrapper<__VA_ARGS__ const> x) { \
void* aligned_storage = reinterpret_cast<void*>( \
(reinterpret_cast<size_t>(storage) & \
~(size_t(EIGENPY_DEFAULT_ALIGN_BYTES - 1))) + \
EIGENPY_DEFAULT_ALIGN_BYTES); \
value_holder<__VA_ARGS__>* new_holder = \
new (aligned_storage) value_holder<__VA_ARGS__>(instance, x); \
return new_holder; \
} \
}; \
} \
} \
}
#define EIGENPY_DEFINE_STRUCT_ALLOCATOR_SPECIALIZATION(...) \
EIGENPY_DEPRECATED_MACRO(EIGENPY_DEFINE_STRUCT_ALLOCATOR_SPECIALIZATION(), \
"it is no more needed.")
#endif // __eigenpy_memory_hpp__
......@@ -7,26 +7,24 @@
#include "eigenpy/eigen-from-python.hpp"
#include "eigenpy/std-vector.hpp"
template <typename MatType,
typename Allocator = Eigen::aligned_allocator<MatType> >
void printVectorOfMatrix(const std::vector<MatType, Allocator> &Ms) {
template <typename MatType>
void printVectorOfMatrix(
const std::vector<MatType, Eigen::aligned_allocator<MatType> > &Ms) {
const std::size_t n = Ms.size();
for (std::size_t i = 0; i < n; i++) {
std::cout << "el[" << i << "] =\n" << Ms[i] << '\n';
}
}
template <typename MatType,
typename Allocator = Eigen::aligned_allocator<MatType> >
std::vector<MatType, Allocator> copy(
const std::vector<MatType, Allocator> &Ms) {
std::vector<MatType, Allocator> out = Ms;
template <typename MatType>
std::vector<MatType, Eigen::aligned_allocator<MatType> > copy(
const std::vector<MatType, Eigen::aligned_allocator<MatType> > &Ms) {
std::vector<MatType, Eigen::aligned_allocator<MatType> > out = Ms;
return out;
}
template <typename MatType,
typename Allocator = Eigen::aligned_allocator<MatType> >
void setZero(std::vector<MatType, Allocator> &Ms) {
template <typename MatType>
void setZero(std::vector<MatType, Eigen::aligned_allocator<MatType> > &Ms) {
for (std::size_t i = 0; i < Ms.size(); i++) {
Ms[i].setZero();
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment