eigenpy 3.12.0
Bindings between Numpy and Eigen using Boost.Python
Loading...
Searching...
No Matches
register.hpp
1//
2// Copyright (c) 2020 INRIA
3//
4
5#ifndef __eigenpy_register_hpp__
6#define __eigenpy_register_hpp__
7
8#include <algorithm>
9#include <map>
10#include <string>
11#include <typeinfo>
12
13#include "eigenpy/exception.hpp"
14#include "eigenpy/fwd.hpp"
15#include "eigenpy/numpy.hpp"
16
17namespace eigenpy {
18
20struct EIGENPY_DLLAPI Register {
21 static PyArray_Descr *getPyArrayDescr(PyTypeObject *py_type_ptr);
22
23 static PyArray_Descr *getPyArrayDescrFromTypeNum(const int type_num);
24
25 template <typename Scalar>
26 static PyArray_Descr *getPyArrayDescrFromScalarType() {
27 if (!isNumpyNativeType<Scalar>()) {
28 const std::type_info &info = typeid(Scalar);
29 if (instance().type_to_py_type_bindings.find(&info) !=
30 instance().type_to_py_type_bindings.end()) {
31 PyTypeObject *py_type = instance().type_to_py_type_bindings[&info];
32 return instance().py_array_descr_bindings[py_type];
33 } else
34 return nullptr;
35 } else {
36 PyArray_Descr *new_descr =
37 call_PyArray_DescrFromType(NumpyEquivalentType<Scalar>::type_code);
38 return new_descr;
39 }
40 }
41
42 template <typename Scalar>
43 static bool isRegistered() {
44 return isRegistered(Register::getPyType<Scalar>());
45 }
46
47 static bool isRegistered(PyTypeObject *py_type_ptr);
48
49 static int getTypeCode(PyTypeObject *py_type_ptr);
50
51 template <typename Scalar>
52 static PyTypeObject *getPyType() {
53 if (!isNumpyNativeType<Scalar>()) {
54 const PyTypeObject *const_py_type_ptr =
55 bp::converter::registered_pytype<Scalar>::get_pytype();
56 if (const_py_type_ptr == NULL) {
57 std::stringstream ss;
58 ss << "The type " << typeid(Scalar).name()
59 << " does not have a registered converter inside Boot.Python."
60 << std::endl;
61 throw std::invalid_argument(ss.str());
62 }
63 PyTypeObject *py_type_ptr = const_cast<PyTypeObject *>(const_py_type_ptr);
64 return py_type_ptr;
65 } else {
66 PyArray_Descr *new_descr =
67 call_PyArray_DescrFromType(NumpyEquivalentType<Scalar>::type_code);
68 return new_descr->typeobj;
69 }
70 }
71
72 template <typename Scalar>
73 static PyArray_Descr *getPyArrayDescr() {
74 if (!isNumpyNativeType<Scalar>()) {
75 return getPyArrayDescr(getPyType<Scalar>());
76 } else {
77 return call_PyArray_DescrFromType(NumpyEquivalentType<Scalar>::type_code);
78 }
79 }
80
81 template <typename Scalar>
82 static int getTypeCode() {
83 if (isNumpyNativeType<Scalar>())
84 return NumpyEquivalentType<Scalar>::type_code;
85 else {
86 const std::type_info &info = typeid(Scalar);
87 if (instance().type_to_py_type_bindings.find(&info) !=
88 instance().type_to_py_type_bindings.end()) {
89 PyTypeObject *py_type = instance().type_to_py_type_bindings[&info];
90 int code = instance().py_array_code_bindings[py_type];
91
92 return code;
93 } else
94 return -1; // type not registered
95 }
96 }
97
98 static int registerNewType(
99 PyTypeObject *py_type_ptr, const std::type_info *type_info_ptr,
100 const int type_size, const int alignment, PyArray_GetItemFunc *getitem,
101 PyArray_SetItemFunc *setitem, PyArray_NonzeroFunc *nonzero,
102 PyArray_CopySwapFunc *copyswap, PyArray_CopySwapNFunc *copyswapn,
103 PyArray_DotFunc *dotfunc, PyArray_FillFunc *fill,
104 PyArray_FillWithScalarFunc *fillwithscalar);
105
106 static Register &instance();
107
108 private:
109 Register() {};
110
111 struct Compare_PyTypeObject {
112 bool operator()(const PyTypeObject *a, const PyTypeObject *b) const {
113 return std::string(a->tp_name) < std::string(b->tp_name);
114 }
115 };
116
117 struct Compare_TypeInfo {
118 bool operator()(const std::type_info *a, const std::type_info *b) const {
119 return std::string(a->name()) < std::string(b->name());
120 }
121 };
122
123 typedef std::map<const std::type_info *, PyTypeObject *, Compare_TypeInfo>
124 MapInfo;
125 MapInfo type_to_py_type_bindings;
126
127 typedef std::map<PyTypeObject *, PyArray_Descr *, Compare_PyTypeObject>
128 MapDescr;
129 MapDescr py_array_descr_bindings;
130
131 typedef std::map<PyTypeObject *, int, Compare_PyTypeObject> MapCode;
132 MapCode py_array_code_bindings;
133};
134
135} // namespace eigenpy
136
137#endif // __eigenpy_register_hpp__