Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
pybind11
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
pybind11
Commits
0d765f4a
Commit
0d765f4a
authored
Mar 21, 2017
by
Dean Moldovan
Committed by
Wenzel Jakob
Mar 22, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support class-specific operator new and delete
Fixes #754.
parent
b0292c1d
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
52 additions
and
2 deletions
+52
-2
include/pybind11/attr.h
+3
-0
include/pybind11/cast.h
+1
-0
include/pybind11/class_support.h
+1
-1
include/pybind11/common.h
+7
-0
include/pybind11/pybind11.h
+16
-1
tests/test_eigen.cpp
+14
-0
tests/test_eigen.py
+10
-0
No files found.
include/pybind11/attr.h
View file @
0d765f4a
...
@@ -174,6 +174,9 @@ struct type_record {
...
@@ -174,6 +174,9 @@ struct type_record {
/// How large is pybind11::instance<type>?
/// How large is pybind11::instance<type>?
size_t
instance_size
=
0
;
size_t
instance_size
=
0
;
/// The global operator new can be overridden with a class-specific variant
void
*
(
*
operator_new
)(
size_t
)
=
::
operator
new
;
/// Function pointer to class_<..>::init_holder
/// Function pointer to class_<..>::init_holder
void
(
*
init_holder
)(
PyObject
*
,
const
void
*
)
=
nullptr
;
void
(
*
init_holder
)(
PyObject
*
,
const
void
*
)
=
nullptr
;
...
...
include/pybind11/cast.h
View file @
0d765f4a
...
@@ -25,6 +25,7 @@ inline PyTypeObject *make_default_metaclass();
...
@@ -25,6 +25,7 @@ inline PyTypeObject *make_default_metaclass();
struct
type_info
{
struct
type_info
{
PyTypeObject
*
type
;
PyTypeObject
*
type
;
size_t
type_size
;
size_t
type_size
;
void
*
(
*
operator_new
)(
size_t
);
void
(
*
init_holder
)(
PyObject
*
,
const
void
*
);
void
(
*
init_holder
)(
PyObject
*
,
const
void
*
);
void
(
*
dealloc
)(
PyObject
*
);
void
(
*
dealloc
)(
PyObject
*
);
std
::
vector
<
PyObject
*
(
*
)(
PyObject
*
,
PyTypeObject
*
)
>
implicit_conversions
;
std
::
vector
<
PyObject
*
(
*
)(
PyObject
*
,
PyTypeObject
*
)
>
implicit_conversions
;
...
...
include/pybind11/class_support.h
View file @
0d765f4a
...
@@ -183,7 +183,7 @@ extern "C" inline PyObject *pybind11_object_new(PyTypeObject *type, PyObject *,
...
@@ -183,7 +183,7 @@ extern "C" inline PyObject *pybind11_object_new(PyTypeObject *type, PyObject *,
PyObject
*
self
=
type
->
tp_alloc
(
type
,
0
);
PyObject
*
self
=
type
->
tp_alloc
(
type
,
0
);
auto
instance
=
(
instance_essentials
<
void
>
*
)
self
;
auto
instance
=
(
instance_essentials
<
void
>
*
)
self
;
auto
tinfo
=
get_type_info
(
type
);
auto
tinfo
=
get_type_info
(
type
);
instance
->
value
=
::
operator
new
(
tinfo
->
type_size
);
instance
->
value
=
tinfo
->
operator_
new
(
tinfo
->
type_size
);
instance
->
owned
=
true
;
instance
->
owned
=
true
;
instance
->
holder_constructed
=
false
;
instance
->
holder_constructed
=
false
;
get_internals
().
registered_instances
.
emplace
(
instance
->
value
,
self
);
get_internals
().
registered_instances
.
emplace
(
instance
->
value
,
self
);
...
...
include/pybind11/common.h
View file @
0d765f4a
...
@@ -427,6 +427,13 @@ template<size_t N> using make_index_sequence = typename make_index_sequence_impl
...
@@ -427,6 +427,13 @@ template<size_t N> using make_index_sequence = typename make_index_sequence_impl
template
<
bool
B
>
using
bool_constant
=
std
::
integral_constant
<
bool
,
B
>
;
template
<
bool
B
>
using
bool_constant
=
std
::
integral_constant
<
bool
,
B
>
;
template
<
typename
T
>
struct
negation
:
bool_constant
<!
T
::
value
>
{
};
template
<
typename
T
>
struct
negation
:
bool_constant
<!
T
::
value
>
{
};
#ifdef __cpp_lib_void_t
using
std
::
void_t
;
#else
template
<
typename
...
>
struct
void_t_impl
{
using
type
=
void
;
};
template
<
typename
...
Ts
>
using
void_t
=
typename
void_t_impl
<
Ts
...
>::
type
;
#endif
/// Compile-time all/any/none of that check the boolean value of all template types
/// Compile-time all/any/none of that check the boolean value of all template types
#ifdef __cpp_fold_expressions
#ifdef __cpp_fold_expressions
template
<
class
...
Ts
>
using
all_of
=
bool_constant
<
(
Ts
::
value
&&
...)
>
;
template
<
class
...
Ts
>
using
all_of
=
bool_constant
<
(
Ts
::
value
&&
...)
>
;
...
...
include/pybind11/pybind11.h
View file @
0d765f4a
...
@@ -803,6 +803,7 @@ protected:
...
@@ -803,6 +803,7 @@ protected:
auto
*
tinfo
=
new
detail
::
type_info
();
auto
*
tinfo
=
new
detail
::
type_info
();
tinfo
->
type
=
(
PyTypeObject
*
)
m_ptr
;
tinfo
->
type
=
(
PyTypeObject
*
)
m_ptr
;
tinfo
->
type_size
=
rec
.
type_size
;
tinfo
->
type_size
=
rec
.
type_size
;
tinfo
->
operator_new
=
rec
.
operator_new
;
tinfo
->
init_holder
=
rec
.
init_holder
;
tinfo
->
init_holder
=
rec
.
init_holder
;
tinfo
->
dealloc
=
rec
.
dealloc
;
tinfo
->
dealloc
=
rec
.
dealloc
;
...
@@ -860,6 +861,18 @@ protected:
...
@@ -860,6 +861,18 @@ protected:
}
}
};
};
/// Set the pointer to operator new if it exists. The cast is needed because it can be overloaded.
template
<
typename
T
,
typename
=
void_t
<
decltype
(
static_cast
<
void
*
(
*
)(
size_t
)
>
(
T
::
operator
new
))
>>
void
set_operator_new
(
type_record
*
r
)
{
r
->
operator_new
=
&
T
::
operator
new
;
}
template
<
typename
>
void
set_operator_new
(...)
{
}
/// Call class-specific delete if it exists or global otherwise. Can also be an overload set.
template
<
typename
T
,
typename
=
void_t
<
decltype
(
static_cast
<
void
(
*
)(
void
*
)
>
(
T
::
operator
delete
))
>>
void
call_operator_delete
(
T
*
p
)
{
T
::
operator
delete
(
p
);
}
inline
void
call_operator_delete
(
void
*
p
)
{
::
operator
delete
(
p
);
}
NAMESPACE_END
(
detail
)
NAMESPACE_END
(
detail
)
template
<
typename
type_
,
typename
...
options
>
template
<
typename
type_
,
typename
...
options
>
...
@@ -905,6 +918,8 @@ public:
...
@@ -905,6 +918,8 @@ public:
record
.
dealloc
=
dealloc
;
record
.
dealloc
=
dealloc
;
record
.
default_holder
=
std
::
is_same
<
holder_type
,
std
::
unique_ptr
<
type
>>::
value
;
record
.
default_holder
=
std
::
is_same
<
holder_type
,
std
::
unique_ptr
<
type
>>::
value
;
set_operator_new
<
type
>
(
&
record
);
/* Register base classes specified via template arguments to class_, if any */
/* Register base classes specified via template arguments to class_, if any */
bool
unused
[]
=
{
(
add_base
<
options
>
(
record
),
false
)...,
false
};
bool
unused
[]
=
{
(
add_base
<
options
>
(
record
),
false
)...,
false
};
(
void
)
unused
;
(
void
)
unused
;
...
@@ -1125,7 +1140,7 @@ private:
...
@@ -1125,7 +1140,7 @@ private:
if
(
inst
->
holder_constructed
)
if
(
inst
->
holder_constructed
)
inst
->
holder
.
~
holder_type
();
inst
->
holder
.
~
holder_type
();
else
if
(
inst
->
owned
)
else
if
(
inst
->
owned
)
::
operator
delete
(
inst
->
value
);
detail
::
call_operator_
delete
(
inst
->
value
);
}
}
static
detail
::
function_record
*
get_function_record
(
handle
h
)
{
static
detail
::
function_record
*
get_function_record
(
handle
h
)
{
...
...
tests/test_eigen.cpp
View file @
0d765f4a
...
@@ -60,6 +60,15 @@ template <typename MatrixArgType> Eigen::MatrixXd adjust_matrix(MatrixArgType m)
...
@@ -60,6 +60,15 @@ template <typename MatrixArgType> Eigen::MatrixXd adjust_matrix(MatrixArgType m)
return
ret
;
return
ret
;
}
}
struct
CustomOperatorNew
{
CustomOperatorNew
()
=
default
;
Eigen
::
Matrix4d
a
=
Eigen
::
Matrix4d
::
Zero
();
Eigen
::
Matrix4d
b
=
Eigen
::
Matrix4d
::
Identity
();
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
;
};
test_initializer
eigen
([](
py
::
module
&
m
)
{
test_initializer
eigen
([](
py
::
module
&
m
)
{
typedef
Eigen
::
Matrix
<
float
,
5
,
6
,
Eigen
::
RowMajor
>
FixedMatrixR
;
typedef
Eigen
::
Matrix
<
float
,
5
,
6
,
Eigen
::
RowMajor
>
FixedMatrixR
;
typedef
Eigen
::
Matrix
<
float
,
5
,
6
>
FixedMatrixC
;
typedef
Eigen
::
Matrix
<
float
,
5
,
6
>
FixedMatrixC
;
...
@@ -277,4 +286,9 @@ test_initializer eigen([](py::module &m) {
...
@@ -277,4 +286,9 @@ test_initializer eigen([](py::module &m) {
// requiring a copy!) because the stride value can be safely ignored on a size-1 dimension.
// requiring a copy!) because the stride value can be safely ignored on a size-1 dimension.
m
.
def
(
"iss738_f1"
,
&
adjust_matrix
<
const
Eigen
::
Ref
<
const
Eigen
::
MatrixXd
>
&>
,
py
::
arg
().
noconvert
());
m
.
def
(
"iss738_f1"
,
&
adjust_matrix
<
const
Eigen
::
Ref
<
const
Eigen
::
MatrixXd
>
&>
,
py
::
arg
().
noconvert
());
m
.
def
(
"iss738_f2"
,
&
adjust_matrix
<
const
Eigen
::
Ref
<
const
Eigen
::
Matrix
<
double
,
-
1
,
-
1
,
Eigen
::
RowMajor
>>
&>
,
py
::
arg
().
noconvert
());
m
.
def
(
"iss738_f2"
,
&
adjust_matrix
<
const
Eigen
::
Ref
<
const
Eigen
::
Matrix
<
double
,
-
1
,
-
1
,
Eigen
::
RowMajor
>>
&>
,
py
::
arg
().
noconvert
());
py
::
class_
<
CustomOperatorNew
>
(
m
,
"CustomOperatorNew"
)
.
def
(
py
::
init
<>
())
.
def_readonly
(
"a"
,
&
CustomOperatorNew
::
a
)
.
def_readonly
(
"b"
,
&
CustomOperatorNew
::
b
);
});
});
tests/test_eigen.py
View file @
0d765f4a
...
@@ -614,3 +614,13 @@ def test_issue738():
...
@@ -614,3 +614,13 @@ def test_issue738():
assert
np
.
all
(
iss738_f2
(
np
.
array
([[
1.
,
2
,
3
]]))
==
np
.
array
([[
1.
,
102
,
203
]]))
assert
np
.
all
(
iss738_f2
(
np
.
array
([[
1.
,
2
,
3
]]))
==
np
.
array
([[
1.
,
102
,
203
]]))
assert
np
.
all
(
iss738_f2
(
np
.
array
([[
1.
],
[
2
],
[
3
]]))
==
np
.
array
([[
1.
],
[
12
],
[
23
]]))
assert
np
.
all
(
iss738_f2
(
np
.
array
([[
1.
],
[
2
],
[
3
]]))
==
np
.
array
([[
1.
],
[
12
],
[
23
]]))
def
test_custom_operator_new
():
"""Using Eigen types as member variables requires a class-specific
operator new with proper alignment"""
from
pybind11_tests
import
CustomOperatorNew
o
=
CustomOperatorNew
()
np
.
testing
.
assert_allclose
(
o
.
a
,
0.0
)
np
.
testing
.
assert_allclose
(
o
.
b
.
diagonal
(),
1.0
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment