Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
gaoqiong
pybind11
Commits
ddbc74c6
Commit
ddbc74c6
authored
Feb 07, 2022
by
Ralf W. Grosse-Kunstleve
Committed by
Ralf W. Grosse-Kunstleve
Feb 08, 2022
Browse files
Adding .clang-tidy readability-braces-around-statements option.
clang-tidy automatic changes. NO manual changes.
parent
8581584e
Changes
49
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
931 additions
and
460 deletions
+931
-460
.clang-tidy
.clang-tidy
+1
-0
include/pybind11/attr.h
include/pybind11/attr.h
+21
-11
include/pybind11/buffer_info.h
include/pybind11/buffer_info.h
+10
-5
include/pybind11/cast.h
include/pybind11/cast.h
+77
-36
include/pybind11/chrono.h
include/pybind11/chrono.h
+12
-5
include/pybind11/complex.h
include/pybind11/complex.h
+4
-2
include/pybind11/detail/class.h
include/pybind11/detail/class.h
+71
-37
include/pybind11/detail/init.h
include/pybind11/detail/init.h
+21
-10
include/pybind11/detail/internals.h
include/pybind11/detail/internals.h
+5
-2
include/pybind11/detail/type_caster_base.h
include/pybind11/detail/type_caster_base.h
+113
-55
include/pybind11/detail/typeid.h
include/pybind11/detail/typeid.h
+5
-2
include/pybind11/eigen.h
include/pybind11/eigen.h
+59
-27
include/pybind11/embed.h
include/pybind11/embed.h
+12
-6
include/pybind11/eval.h
include/pybind11/eval.h
+8
-4
include/pybind11/functional.h
include/pybind11/functional.h
+9
-4
include/pybind11/gil.h
include/pybind11/gil.h
+9
-5
include/pybind11/iostream.h
include/pybind11/iostream.h
+14
-8
include/pybind11/numpy.h
include/pybind11/numpy.h
+114
-59
include/pybind11/pybind11.h
include/pybind11/pybind11.h
+244
-130
include/pybind11/pytypes.h
include/pybind11/pytypes.h
+122
-52
No files found.
.clang-tidy
View file @
ddbc74c6
...
...
@@ -31,6 +31,7 @@ modernize-use-override,
modernize-use-using,
*performance*,
readability-avoid-const-params-in-decls,
readability-braces-around-statements,
readability-const-return-type,
readability-container-size-empty,
readability-delete-null-pointer,
...
...
include/pybind11/attr.h
View file @
ddbc74c6
...
...
@@ -330,11 +330,13 @@ struct type_record {
bases
.
append
((
PyObject
*
)
base_info
->
type
);
if
(
base_info
->
type
->
tp_dictoffset
!=
0
)
if
(
base_info
->
type
->
tp_dictoffset
!=
0
)
{
dynamic_attr
=
true
;
}
if
(
caster
)
if
(
caster
)
{
base_info
->
implicit_casts
.
emplace_back
(
type
,
caster
);
}
}
};
...
...
@@ -410,13 +412,16 @@ template <> struct process_attribute<is_new_style_constructor> : process_attribu
};
inline
void
check_kw_only_arg
(
const
arg
&
a
,
function_record
*
r
)
{
if
(
r
->
args
.
size
()
>
r
->
nargs_pos
&&
(
!
a
.
name
||
a
.
name
[
0
]
==
'\0'
))
pybind11_fail
(
"arg(): cannot specify an unnamed argument after a kw_only() annotation or args() argument"
);
if
(
r
->
args
.
size
()
>
r
->
nargs_pos
&&
(
!
a
.
name
||
a
.
name
[
0
]
==
'\0'
))
{
pybind11_fail
(
"arg(): cannot specify an unnamed argument after a kw_only() annotation or "
"args() argument"
);
}
}
inline
void
append_self_arg_if_needed
(
function_record
*
r
)
{
if
(
r
->
is_method
&&
r
->
args
.
empty
())
r
->
args
.
emplace_back
(
"self"
,
nullptr
,
handle
(),
/*convert=*/
true
,
/*none=*/
false
);
if
(
r
->
is_method
&&
r
->
args
.
empty
())
{
r
->
args
.
emplace_back
(
"self"
,
nullptr
,
handle
(),
/*convert=*/
true
,
/*none=*/
false
);
}
}
/// Process a keyword argument attribute (*without* a default value)
...
...
@@ -432,8 +437,10 @@ template <> struct process_attribute<arg> : process_attribute_default<arg> {
/// Process a keyword argument attribute (*with* a default value)
template
<
>
struct
process_attribute
<
arg_v
>
:
process_attribute_default
<
arg_v
>
{
static
void
init
(
const
arg_v
&
a
,
function_record
*
r
)
{
if
(
r
->
is_method
&&
r
->
args
.
empty
())
r
->
args
.
emplace_back
(
"self"
,
/*descr=*/
nullptr
,
/*parent=*/
handle
(),
/*convert=*/
true
,
/*none=*/
false
);
if
(
r
->
is_method
&&
r
->
args
.
empty
())
{
r
->
args
.
emplace_back
(
"self"
,
/*descr=*/
nullptr
,
/*parent=*/
handle
(),
/*convert=*/
true
,
/*none=*/
false
);
}
if
(
!
a
.
value
)
{
#if !defined(NDEBUG)
...
...
@@ -466,8 +473,10 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
template
<
>
struct
process_attribute
<
kw_only
>
:
process_attribute_default
<
kw_only
>
{
static
void
init
(
const
kw_only
&
,
function_record
*
r
)
{
append_self_arg_if_needed
(
r
);
if
(
r
->
has_args
&&
r
->
nargs_pos
!=
static_cast
<
std
::
uint16_t
>
(
r
->
args
.
size
()))
pybind11_fail
(
"Mismatched args() and kw_only(): they must occur at the same relative argument location (or omit kw_only() entirely)"
);
if
(
r
->
has_args
&&
r
->
nargs_pos
!=
static_cast
<
std
::
uint16_t
>
(
r
->
args
.
size
()))
{
pybind11_fail
(
"Mismatched args() and kw_only(): they must occur at the same relative "
"argument location (or omit kw_only() entirely)"
);
}
r
->
nargs_pos
=
static_cast
<
std
::
uint16_t
>
(
r
->
args
.
size
());
}
};
...
...
@@ -477,8 +486,9 @@ template <> struct process_attribute<pos_only> : process_attribute_default<pos_o
static
void
init
(
const
pos_only
&
,
function_record
*
r
)
{
append_self_arg_if_needed
(
r
);
r
->
nargs_pos_only
=
static_cast
<
std
::
uint16_t
>
(
r
->
args
.
size
());
if
(
r
->
nargs_pos_only
>
r
->
nargs_pos
)
if
(
r
->
nargs_pos_only
>
r
->
nargs_pos
)
{
pybind11_fail
(
"pos_only(): cannot follow a py::args() argument"
);
}
// It also can't follow a kw_only, but a static_assert in pybind11.h checks that
}
};
...
...
include/pybind11/buffer_info.h
View file @
ddbc74c6
...
...
@@ -19,9 +19,11 @@ PYBIND11_NAMESPACE_BEGIN(detail)
inline
std
::
vector
<
ssize_t
>
c_strides
(
const
std
::
vector
<
ssize_t
>
&
shape
,
ssize_t
itemsize
)
{
auto
ndim
=
shape
.
size
();
std
::
vector
<
ssize_t
>
strides
(
ndim
,
itemsize
);
if
(
ndim
>
0
)
for
(
size_t
i
=
ndim
-
1
;
i
>
0
;
--
i
)
if
(
ndim
>
0
)
{
for
(
size_t
i
=
ndim
-
1
;
i
>
0
;
--
i
)
{
strides
[
i
-
1
]
=
strides
[
i
]
*
shape
[
i
];
}
}
return
strides
;
}
...
...
@@ -29,8 +31,9 @@ inline std::vector<ssize_t> c_strides(const std::vector<ssize_t> &shape, ssize_t
inline
std
::
vector
<
ssize_t
>
f_strides
(
const
std
::
vector
<
ssize_t
>
&
shape
,
ssize_t
itemsize
)
{
auto
ndim
=
shape
.
size
();
std
::
vector
<
ssize_t
>
strides
(
ndim
,
itemsize
);
for
(
size_t
i
=
1
;
i
<
ndim
;
++
i
)
for
(
size_t
i
=
1
;
i
<
ndim
;
++
i
)
{
strides
[
i
]
=
strides
[
i
-
1
]
*
shape
[
i
-
1
];
}
return
strides
;
}
...
...
@@ -53,10 +56,12 @@ struct buffer_info {
detail
::
any_container
<
ssize_t
>
shape_in
,
detail
::
any_container
<
ssize_t
>
strides_in
,
bool
readonly
=
false
)
:
ptr
(
ptr
),
itemsize
(
itemsize
),
size
(
1
),
format
(
format
),
ndim
(
ndim
),
shape
(
std
::
move
(
shape_in
)),
strides
(
std
::
move
(
strides_in
)),
readonly
(
readonly
)
{
if
(
ndim
!=
(
ssize_t
)
shape
.
size
()
||
ndim
!=
(
ssize_t
)
strides
.
size
())
if
(
ndim
!=
(
ssize_t
)
shape
.
size
()
||
ndim
!=
(
ssize_t
)
strides
.
size
())
{
pybind11_fail
(
"buffer_info: ndim doesn't match shape and/or strides length"
);
for
(
size_t
i
=
0
;
i
<
(
size_t
)
ndim
;
++
i
)
}
for
(
size_t
i
=
0
;
i
<
(
size_t
)
ndim
;
++
i
)
{
size
*=
shape
[
i
];
}
}
template
<
typename
T
>
...
...
include/pybind11/cast.h
View file @
ddbc74c6
...
...
@@ -60,8 +60,10 @@ public:
static
constexpr
auto
name
=
caster_t
::
name
;
static
handle
cast
(
const
std
::
reference_wrapper
<
type
>
&
src
,
return_value_policy
policy
,
handle
parent
)
{
// It is definitely wrong to take ownership of this pointer, so mask that rvp
if
(
policy
==
return_value_policy
::
take_ownership
||
policy
==
return_value_policy
::
automatic
)
if
(
policy
==
return_value_policy
::
take_ownership
||
policy
==
return_value_policy
::
automatic
)
{
policy
=
return_value_policy
::
automatic_reference
;
}
return
caster_t
::
cast
(
&
src
.
get
(),
policy
,
parent
);
}
template
<
typename
T
>
using
cast_op_type
=
std
::
reference_wrapper
<
type
>
;
...
...
@@ -112,8 +114,9 @@ public:
bool
load
(
handle
src
,
bool
convert
)
{
py_type
py_value
;
if
(
!
src
)
if
(
!
src
)
{
return
false
;
}
#if !defined(PYPY_VERSION)
auto
index_check
=
[](
PyObject
*
o
)
{
return
PyIndex_Check
(
o
);
};
...
...
@@ -124,10 +127,11 @@ public:
#endif
if
(
std
::
is_floating_point
<
T
>::
value
)
{
if
(
convert
||
PyFloat_Check
(
src
.
ptr
()))
if
(
convert
||
PyFloat_Check
(
src
.
ptr
()))
{
py_value
=
(
py_type
)
PyFloat_AsDouble
(
src
.
ptr
());
else
}
else
{
return
false
;
}
}
else
if
(
PyFloat_Check
(
src
.
ptr
())
||
(
!
convert
&&
!
PYBIND11_LONG_CHECK
(
src
.
ptr
())
&&
!
index_check
(
src
.
ptr
())))
{
return
false
;
...
...
@@ -214,8 +218,9 @@ public:
template
<
typename
T
>
struct
void_caster
{
public:
bool
load
(
handle
src
,
bool
)
{
if
(
src
&&
src
.
is_none
())
if
(
src
&&
src
.
is_none
())
{
return
true
;
}
return
false
;
}
static
handle
cast
(
T
,
return_value_policy
/* policy */
,
handle
/* parent */
)
{
...
...
@@ -257,8 +262,9 @@ public:
}
static
handle
cast
(
const
void
*
ptr
,
return_value_policy
/* policy */
,
handle
/* parent */
)
{
if
(
ptr
)
if
(
ptr
)
{
return
capsule
(
ptr
).
release
();
}
return
none
().
inc_ref
();
}
...
...
@@ -274,7 +280,9 @@ template <> class type_caster<std::nullptr_t> : public void_caster<std::nullptr_
template
<
>
class
type_caster
<
bool
>
{
public:
bool
load
(
handle
src
,
bool
convert
)
{
if
(
!
src
)
return
false
;
if
(
!
src
)
{
return
false
;
}
if
(
src
.
ptr
()
==
Py_True
)
{
value
=
true
;
return
true
;
...
...
@@ -391,8 +399,9 @@ template <typename StringType, bool IsView = false> struct string_caster {
value
=
StringType
(
buffer
,
length
);
// If we're loading a string_view we need to keep the encoded Python object alive:
if
(
IsView
)
if
(
IsView
)
{
loader_life_support
::
add_patient
(
utfNbytes
);
}
return
true
;
}
...
...
@@ -401,7 +410,9 @@ template <typename StringType, bool IsView = false> struct string_caster {
const
char
*
buffer
=
reinterpret_cast
<
const
char
*>
(
src
.
data
());
auto
nbytes
=
ssize_t
(
src
.
size
()
*
sizeof
(
CharT
));
handle
s
=
decode_utfN
(
buffer
,
nbytes
);
if
(
!
s
)
throw
error_already_set
();
if
(
!
s
)
{
throw
error_already_set
();
}
return
s
;
}
...
...
@@ -463,10 +474,14 @@ template <typename CharT> struct type_caster<CharT, enable_if_t<is_std_char_type
CharT
one_char
=
0
;
public:
bool
load
(
handle
src
,
bool
convert
)
{
if
(
!
src
)
return
false
;
if
(
!
src
)
{
return
false
;
}
if
(
src
.
is_none
())
{
// Defer accepting None to other overloads (if we aren't in convert mode):
if
(
!
convert
)
return
false
;
if
(
!
convert
)
{
return
false
;
}
none
=
true
;
return
true
;
}
...
...
@@ -474,14 +489,18 @@ public:
}
static
handle
cast
(
const
CharT
*
src
,
return_value_policy
policy
,
handle
parent
)
{
if
(
src
==
nullptr
)
return
pybind11
::
none
().
inc_ref
();
if
(
src
==
nullptr
)
{
return
pybind11
::
none
().
inc_ref
();
}
return
StringCaster
::
cast
(
StringType
(
src
),
policy
,
parent
);
}
static
handle
cast
(
CharT
src
,
return_value_policy
policy
,
handle
parent
)
{
if
(
std
::
is_same
<
char
,
CharT
>::
value
)
{
handle
s
=
PyUnicode_DecodeLatin1
((
const
char
*
)
&
src
,
1
,
nullptr
);
if
(
!
s
)
throw
error_already_set
();
if
(
!
s
)
{
throw
error_already_set
();
}
return
s
;
}
return
StringCaster
::
cast
(
StringType
(
1
,
src
),
policy
,
parent
);
...
...
@@ -491,13 +510,15 @@ public:
return
none
?
nullptr
:
const_cast
<
CharT
*>
(
static_cast
<
StringType
&>
(
str_caster
).
c_str
());
}
explicit
operator
CharT
&
()
{
if
(
none
)
if
(
none
)
{
throw
value_error
(
"Cannot convert None to a character"
);
}
auto
&
value
=
static_cast
<
StringType
&>
(
str_caster
);
size_t
str_len
=
value
.
size
();
if
(
str_len
==
0
)
if
(
str_len
==
0
)
{
throw
value_error
(
"Cannot convert empty string to a character"
);
}
// If we're in UTF-8 mode, we have two possible failures: one for a unicode character that
// is too high, and one for multiple unicode characters (caught later), so we need to figure
...
...
@@ -531,12 +552,14 @@ public:
// string was too long" error).
else
if
(
PYBIND11_SILENCE_MSVC_C4127
(
StringCaster
::
UTF_N
==
16
)
&&
str_len
==
2
)
{
one_char
=
static_cast
<
CharT
>
(
value
[
0
]);
if
(
one_char
>=
0xD800
&&
one_char
<
0xE000
)
if
(
one_char
>=
0xD800
&&
one_char
<
0xE000
)
{
throw
value_error
(
"Character code point not in range(0x10000)"
);
}
}
if
(
str_len
!=
1
)
if
(
str_len
!=
1
)
{
throw
value_error
(
"Expected a character, but multi-character string found"
);
}
one_char
=
value
[
0
];
return
one_char
;
...
...
@@ -554,11 +577,13 @@ template <template<typename...> class Tuple, typename... Ts> class tuple_caster
public:
bool
load
(
handle
src
,
bool
convert
)
{
if
(
!
isinstance
<
sequence
>
(
src
))
if
(
!
isinstance
<
sequence
>
(
src
))
{
return
false
;
}
const
auto
seq
=
reinterpret_borrow
<
sequence
>
(
src
);
if
(
seq
.
size
()
!=
size
)
if
(
seq
.
size
()
!=
size
)
{
return
false
;
}
return
load_impl
(
seq
,
convert
,
indices
{});
}
...
...
@@ -570,7 +595,9 @@ public:
// copied from the PYBIND11_TYPE_CASTER macro
template
<
typename
T
>
static
handle
cast
(
T
*
src
,
return_value_policy
policy
,
handle
parent
)
{
if
(
!
src
)
return
none
().
release
();
if
(
!
src
)
{
return
none
().
release
();
}
if
(
policy
==
return_value_policy
::
take_ownership
)
{
auto
h
=
cast
(
std
::
move
(
*
src
),
policy
,
parent
);
delete
src
;
...
...
@@ -597,8 +624,9 @@ protected:
template
<
size_t
...
Is
>
bool
load_impl
(
const
sequence
&
seq
,
bool
convert
,
index_sequence
<
Is
...
>
)
{
#ifdef __cpp_fold_expressions
if
((...
||
!
std
::
get
<
Is
>
(
subcasters
).
load
(
seq
[
Is
],
convert
)))
if
((...
||
!
std
::
get
<
Is
>
(
subcasters
).
load
(
seq
[
Is
],
convert
)))
{
return
false
;
}
#else
for
(
bool
r
:
{
std
::
get
<
Is
>
(
subcasters
).
load
(
seq
[
Is
],
convert
)...})
if
(
!
r
)
...
...
@@ -615,13 +643,16 @@ protected:
std
::
array
<
object
,
size
>
entries
{{
reinterpret_steal
<
object
>
(
make_caster
<
Ts
>::
cast
(
std
::
get
<
Is
>
(
std
::
forward
<
T
>
(
src
)),
policy
,
parent
))...
}};
for
(
const
auto
&
entry
:
entries
)
if
(
!
entry
)
for
(
const
auto
&
entry
:
entries
)
{
if
(
!
entry
)
{
return
handle
();
}
}
tuple
result
(
size
);
int
counter
=
0
;
for
(
auto
&
entry
:
entries
)
for
(
auto
&
entry
:
entries
)
{
PyTuple_SET_ITEM
(
result
.
ptr
(),
counter
++
,
entry
.
release
().
ptr
());
}
return
result
.
release
();
}
...
...
@@ -676,8 +707,9 @@ public:
protected:
friend
class
type_caster_generic
;
void
check_holder_compat
()
{
if
(
typeinfo
->
default_holder
)
if
(
typeinfo
->
default_holder
)
{
throw
cast_error
(
"Unable to load a custom holder type from a default-holder instance"
);
}
}
bool
load_value
(
value_and_holder
&&
v_h
)
{
...
...
@@ -793,8 +825,9 @@ struct pyobject_caster {
return
true
;
}
#endif
if
(
!
isinstance
<
type
>
(
src
))
if
(
!
isinstance
<
type
>
(
src
))
{
return
false
;
}
value
=
reinterpret_borrow
<
type
>
(
src
);
return
true
;
}
...
...
@@ -901,12 +934,14 @@ template <typename T, detail::enable_if_t<!detail::is_pyobject<T>::value, int> =
object
cast
(
T
&&
value
,
return_value_policy
policy
=
return_value_policy
::
automatic_reference
,
handle
parent
=
handle
())
{
using
no_ref_T
=
typename
std
::
remove_reference
<
T
>::
type
;
if
(
policy
==
return_value_policy
::
automatic
)
if
(
policy
==
return_value_policy
::
automatic
)
{
policy
=
std
::
is_pointer
<
no_ref_T
>::
value
?
return_value_policy
::
take_ownership
:
std
::
is_lvalue_reference
<
T
>::
value
?
return_value_policy
::
copy
:
return_value_policy
::
move
;
else
if
(
policy
==
return_value_policy
::
automatic_reference
)
policy
=
std
::
is_pointer
<
no_ref_T
>::
value
?
return_value_policy
::
reference
:
std
::
is_lvalue_reference
<
T
>::
value
?
return_value_policy
::
copy
:
return_value_policy
::
move
;
}
else
if
(
policy
==
return_value_policy
::
automatic_reference
)
{
policy
=
std
::
is_pointer
<
no_ref_T
>::
value
?
return_value_policy
::
reference
:
std
::
is_lvalue_reference
<
T
>::
value
?
return_value_policy
::
copy
:
return_value_policy
::
move
;
}
return
reinterpret_steal
<
object
>
(
detail
::
make_caster
<
T
>::
cast
(
std
::
forward
<
T
>
(
value
),
policy
,
parent
));
}
...
...
@@ -939,8 +974,9 @@ template <typename T> detail::enable_if_t<detail::move_always<T>::value, T> cast
return
move
<
T
>
(
std
::
move
(
object
));
}
template
<
typename
T
>
detail
::
enable_if_t
<
detail
::
move_if_unreferenced
<
T
>::
value
,
T
>
cast
(
object
&&
object
)
{
if
(
object
.
ref_count
()
>
1
)
if
(
object
.
ref_count
()
>
1
)
{
return
cast
<
T
>
(
object
);
}
return
move
<
T
>
(
std
::
move
(
object
));
}
template
<
typename
T
>
detail
::
enable_if_t
<
detail
::
move_never
<
T
>::
value
,
T
>
cast
(
object
&&
object
)
{
...
...
@@ -1018,8 +1054,9 @@ template <return_value_policy policy = return_value_policy::automatic_reference,
}
tuple
result
(
size
);
int
counter
=
0
;
for
(
auto
&
arg_value
:
args
)
for
(
auto
&
arg_value
:
args
)
{
PyTuple_SET_ITEM
(
result
.
ptr
(),
counter
++
,
arg_value
.
release
().
ptr
());
}
return
result
;
}
...
...
@@ -1231,8 +1268,9 @@ public:
/// Call a Python function and pass the collected arguments
object
call
(
PyObject
*
ptr
)
const
{
PyObject
*
result
=
PyObject_CallObject
(
ptr
,
m_args
.
ptr
());
if
(
!
result
)
if
(
!
result
)
{
throw
error_already_set
();
}
return
reinterpret_steal
<
object
>
(
result
);
}
...
...
@@ -1264,8 +1302,9 @@ public:
/// Call a Python function and pass the collected arguments
object
call
(
PyObject
*
ptr
)
const
{
PyObject
*
result
=
PyObject_Call
(
ptr
,
m_args
.
ptr
(),
m_kwargs
.
ptr
());
if
(
!
result
)
if
(
!
result
)
{
throw
error_already_set
();
}
return
reinterpret_steal
<
object
>
(
result
);
}
...
...
@@ -1285,8 +1324,9 @@ private:
}
void
process
(
list
&
args_list
,
detail
::
args_proxy
ap
)
{
for
(
auto
a
:
ap
)
for
(
auto
a
:
ap
)
{
args_list
.
append
(
a
);
}
}
void
process
(
list
&
/*args_list*/
,
arg_v
a
)
{
...
...
@@ -1315,8 +1355,9 @@ private:
}
void
process
(
list
&
/*args_list*/
,
detail
::
kwargs_proxy
kp
)
{
if
(
!
kp
)
if
(
!
kp
)
{
return
;
}
for
(
auto
k
:
reinterpret_borrow
<
dict
>
(
kp
))
{
if
(
m_kwargs
.
contains
(
k
.
first
))
{
#if defined(NDEBUG)
...
...
include/pybind11/chrono.h
View file @
ddbc74c6
...
...
@@ -46,7 +46,9 @@ public:
// Lazy initialise the PyDateTime import
if
(
!
PyDateTimeAPI
)
{
PyDateTime_IMPORT
;
}
if
(
!
src
)
return
false
;
if
(
!
src
)
{
return
false
;
}
// If invoked with datetime.delta object
if
(
PyDelta_Check
(
src
.
ptr
()))
{
value
=
type
(
duration_cast
<
duration
<
rep
,
period
>>
(
...
...
@@ -124,7 +126,9 @@ public:
// Lazy initialise the PyDateTime import
if
(
!
PyDateTimeAPI
)
{
PyDateTime_IMPORT
;
}
if
(
!
src
)
return
false
;
if
(
!
src
)
{
return
false
;
}
std
::
tm
cal
;
microseconds
msecs
;
...
...
@@ -156,8 +160,9 @@ public:
cal
.
tm_year
=
70
;
// earliest available date for Python's datetime
cal
.
tm_isdst
=
-
1
;
msecs
=
microseconds
(
PyDateTime_TIME_GET_MICROSECOND
(
src
.
ptr
()));
}
else
{
return
false
;
}
else
return
false
;
value
=
time_point_cast
<
Duration
>
(
system_clock
::
from_time_t
(
std
::
mktime
(
&
cal
))
+
msecs
);
return
true
;
...
...
@@ -173,8 +178,9 @@ public:
// (cfr. https://github.com/pybind/pybind11/issues/2417)
using
us_t
=
duration
<
int
,
std
::
micro
>
;
auto
us
=
duration_cast
<
us_t
>
(
src
.
time_since_epoch
()
%
seconds
(
1
));
if
(
us
.
count
()
<
0
)
if
(
us
.
count
()
<
0
)
{
us
+=
seconds
(
1
);
}
// Subtract microseconds BEFORE `system_clock::to_time_t`, because:
// > If std::time_t has lower precision, it is implementation-defined whether the value is rounded or truncated.
...
...
@@ -183,8 +189,9 @@ public:
std
::
tm
localtime
;
std
::
tm
*
localtime_ptr
=
localtime_thread_safe
(
&
tt
,
&
localtime
);
if
(
!
localtime_ptr
)
if
(
!
localtime_ptr
)
{
throw
cast_error
(
"Unable to represent system_clock in local time"
);
}
return
PyDateTime_FromDateAndTime
(
localtime
.
tm_year
+
1900
,
localtime
.
tm_mon
+
1
,
localtime
.
tm_mday
,
...
...
include/pybind11/complex.h
View file @
ddbc74c6
...
...
@@ -42,10 +42,12 @@ template <typename T> struct is_fmt_numeric<std::complex<T>, detail::enable_if_t
template
<
typename
T
>
class
type_caster
<
std
::
complex
<
T
>>
{
public:
bool
load
(
handle
src
,
bool
convert
)
{
if
(
!
src
)
if
(
!
src
)
{
return
false
;
if
(
!
convert
&&
!
PyComplex_Check
(
src
.
ptr
()))
}
if
(
!
convert
&&
!
PyComplex_Check
(
src
.
ptr
()))
{
return
false
;
}
Py_complex
result
=
PyComplex_AsCComplex
(
src
.
ptr
());
if
(
result
.
real
==
-
1.0
&&
PyErr_Occurred
())
{
PyErr_Clear
();
...
...
include/pybind11/detail/class.h
View file @
ddbc74c6
...
...
@@ -66,8 +66,9 @@ inline PyTypeObject *make_static_property_type() {
garbage collector (the GC will call type_traverse(), which will in
turn find the newly constructed type in an invalid state) */
auto
heap_type
=
(
PyHeapTypeObject
*
)
PyType_Type
.
tp_alloc
(
&
PyType_Type
,
0
);
if
(
!
heap_type
)
if
(
!
heap_type
)
{
pybind11_fail
(
"make_static_property_type(): error allocating type!"
);
}
heap_type
->
ht_name
=
name_obj
.
inc_ref
().
ptr
();
#ifdef PYBIND11_BUILTIN_QUALNAME
...
...
@@ -81,8 +82,9 @@ inline PyTypeObject *make_static_property_type() {
type
->
tp_descr_get
=
pybind11_static_get
;
type
->
tp_descr_set
=
pybind11_static_set
;
if
(
PyType_Ready
(
type
)
<
0
)
if
(
PyType_Ready
(
type
)
<
0
)
{
pybind11_fail
(
"make_static_property_type(): failure in PyType_Ready()!"
);
}
setattr
((
PyObject
*
)
type
,
"__module__"
,
str
(
"pybind11_builtins"
));
PYBIND11_SET_OLDPY_QUALNAME
(
type
,
name_obj
);
...
...
@@ -209,19 +211,21 @@ extern "C" inline void pybind11_meta_dealloc(PyObject *obj) {
auto
tindex
=
std
::
type_index
(
*
tinfo
->
cpptype
);
internals
.
direct_conversions
.
erase
(
tindex
);
if
(
tinfo
->
module_local
)
if
(
tinfo
->
module_local
)
{
get_local_internals
().
registered_types_cpp
.
erase
(
tindex
);
else
}
else
{
internals
.
registered_types_cpp
.
erase
(
tindex
);
}
internals
.
registered_types_py
.
erase
(
tinfo
->
type
);
// Actually just `std::erase_if`, but that's only available in C++20
auto
&
cache
=
internals
.
inactive_override_cache
;
for
(
auto
it
=
cache
.
begin
(),
last
=
cache
.
end
();
it
!=
last
;
)
{
if
(
it
->
first
==
(
PyObject
*
)
tinfo
->
type
)
if
(
it
->
first
==
(
PyObject
*
)
tinfo
->
type
)
{
it
=
cache
.
erase
(
it
);
else
}
else
{
++
it
;
}
}
delete
tinfo
;
...
...
@@ -242,8 +246,9 @@ inline PyTypeObject* make_default_metaclass() {
garbage collector (the GC will call type_traverse(), which will in
turn find the newly constructed type in an invalid state) */
auto
heap_type
=
(
PyHeapTypeObject
*
)
PyType_Type
.
tp_alloc
(
&
PyType_Type
,
0
);
if
(
!
heap_type
)
if
(
!
heap_type
)
{
pybind11_fail
(
"make_default_metaclass(): error allocating metaclass!"
);
}
heap_type
->
ht_name
=
name_obj
.
inc_ref
().
ptr
();
#ifdef PYBIND11_BUILTIN_QUALNAME
...
...
@@ -264,8 +269,9 @@ inline PyTypeObject* make_default_metaclass() {
type
->
tp_dealloc
=
pybind11_meta_dealloc
;
if
(
PyType_Ready
(
type
)
<
0
)
if
(
PyType_Ready
(
type
)
<
0
)
{
pybind11_fail
(
"make_default_metaclass(): failure in PyType_Ready()!"
);
}
setattr
((
PyObject
*
)
type
,
"__module__"
,
str
(
"pybind11_builtins"
));
PYBIND11_SET_OLDPY_QUALNAME
(
type
,
name_obj
);
...
...
@@ -283,8 +289,9 @@ inline void traverse_offset_bases(void *valueptr, const detail::type_info *tinfo
for
(
auto
&
c
:
parent_tinfo
->
implicit_casts
)
{
if
(
c
.
first
==
tinfo
->
cpptype
)
{
auto
*
parentptr
=
c
.
second
(
valueptr
);
if
(
parentptr
!=
valueptr
)
if
(
parentptr
!=
valueptr
)
{
f
(
parentptr
,
self
);
}
traverse_offset_bases
(
parentptr
,
parent_tinfo
,
self
,
f
);
break
;
}
...
...
@@ -311,14 +318,16 @@ inline bool deregister_instance_impl(void *ptr, instance *self) {
inline
void
register_instance
(
instance
*
self
,
void
*
valptr
,
const
type_info
*
tinfo
)
{
register_instance_impl
(
valptr
,
self
);
if
(
!
tinfo
->
simple_ancestors
)
if
(
!
tinfo
->
simple_ancestors
)
{
traverse_offset_bases
(
valptr
,
tinfo
,
self
,
register_instance_impl
);
}
}
inline
bool
deregister_instance
(
instance
*
self
,
void
*
valptr
,
const
type_info
*
tinfo
)
{
bool
ret
=
deregister_instance_impl
(
valptr
,
self
);
if
(
!
tinfo
->
simple_ancestors
)
if
(
!
tinfo
->
simple_ancestors
)
{
traverse_offset_bases
(
valptr
,
tinfo
,
self
,
deregister_instance_impl
);
}
return
ret
;
}
...
...
@@ -377,8 +386,9 @@ inline void clear_patients(PyObject *self) {
auto
patients
=
std
::
move
(
pos
->
second
);
internals
.
patients
.
erase
(
pos
);
instance
->
has_patients
=
false
;
for
(
PyObject
*&
patient
:
patients
)
for
(
PyObject
*&
patient
:
patients
)
{
Py_CLEAR
(
patient
);
}
}
/// Clears all internal data from the instance and removes it from registered instances in
...
...
@@ -392,25 +402,32 @@ inline void clear_instance(PyObject *self) {
// We have to deregister before we call dealloc because, for virtual MI types, we still
// need to be able to get the parent pointers.
if
(
v_h
.
instance_registered
()
&&
!
deregister_instance
(
instance
,
v_h
.
value_ptr
(),
v_h
.
type
))
pybind11_fail
(
"pybind11_object_dealloc(): Tried to deallocate unregistered instance!"
);
if
(
v_h
.
instance_registered
()
&&
!
deregister_instance
(
instance
,
v_h
.
value_ptr
(),
v_h
.
type
))
{
pybind11_fail
(
"pybind11_object_dealloc(): Tried to deallocate unregistered instance!"
);
}
if
(
instance
->
owned
||
v_h
.
holder_constructed
())
if
(
instance
->
owned
||
v_h
.
holder_constructed
())
{
v_h
.
type
->
dealloc
(
v_h
);
}
}
}
// Deallocate the value/holder layout internals:
instance
->
deallocate_layout
();
if
(
instance
->
weakrefs
)
if
(
instance
->
weakrefs
)
{
PyObject_ClearWeakRefs
(
self
);
}
PyObject
**
dict_ptr
=
_PyObject_GetDictPtr
(
self
);
if
(
dict_ptr
)
if
(
dict_ptr
)
{
Py_CLEAR
(
*
dict_ptr
);
}
if
(
instance
->
has_patients
)
if
(
instance
->
has_patients
)
{
clear_patients
(
self
);
}
}
/// Instance destructor function for all pybind11 types. It calls `type_info.dealloc`
...
...
@@ -448,8 +465,9 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass) {
garbage collector (the GC will call type_traverse(), which will in
turn find the newly constructed type in an invalid state) */
auto
heap_type
=
(
PyHeapTypeObject
*
)
metaclass
->
tp_alloc
(
metaclass
,
0
);
if
(
!
heap_type
)
if
(
!
heap_type
)
{
pybind11_fail
(
"make_object_base_type(): error allocating type!"
);
}
heap_type
->
ht_name
=
name_obj
.
inc_ref
().
ptr
();
#ifdef PYBIND11_BUILTIN_QUALNAME
...
...
@@ -469,8 +487,9 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass) {
/* Support weak references (needed for the keep_alive feature) */
type
->
tp_weaklistoffset
=
offsetof
(
instance
,
weakrefs
);
if
(
PyType_Ready
(
type
)
<
0
)
if
(
PyType_Ready
(
type
)
<
0
)
{
pybind11_fail
(
"PyType_Ready failed in make_object_base_type():"
+
error_string
());
}
setattr
((
PyObject
*
)
type
,
"__module__"
,
str
(
"pybind11_builtins"
));
PYBIND11_SET_OLDPY_QUALNAME
(
type
,
name_obj
);
...
...
@@ -482,8 +501,9 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass) {
/// dynamic_attr: Support for `d = instance.__dict__`.
extern
"C"
inline
PyObject
*
pybind11_get_dict
(
PyObject
*
self
,
void
*
)
{
PyObject
*&
dict
=
*
_PyObject_GetDictPtr
(
self
);
if
(
!
dict
)
if
(
!
dict
)
{
dict
=
PyDict_New
();
}
Py_XINCREF
(
dict
);
return
dict
;
}
...
...
@@ -538,12 +558,14 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
type_info
*
tinfo
=
nullptr
;
for
(
auto
type
:
reinterpret_borrow
<
tuple
>
(
Py_TYPE
(
obj
)
->
tp_mro
))
{
tinfo
=
get_type_info
((
PyTypeObject
*
)
type
.
ptr
());
if
(
tinfo
&&
tinfo
->
get_buffer
)
if
(
tinfo
&&
tinfo
->
get_buffer
)
{
break
;
}
}
if
(
view
==
nullptr
||
!
tinfo
||
!
tinfo
->
get_buffer
)
{
if
(
view
)
if
(
view
)
{
view
->
obj
=
nullptr
;
}
PyErr_SetString
(
PyExc_BufferError
,
"pybind11_getbuffer(): Internal error"
);
return
-
1
;
}
...
...
@@ -561,11 +583,13 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
view
->
buf
=
info
->
ptr
;
view
->
itemsize
=
info
->
itemsize
;
view
->
len
=
view
->
itemsize
;
for
(
auto
s
:
info
->
shape
)
for
(
auto
s
:
info
->
shape
)
{
view
->
len
*=
s
;
}
view
->
readonly
=
static_cast
<
int
>
(
info
->
readonly
);
if
((
flags
&
PyBUF_FORMAT
)
==
PyBUF_FORMAT
)
if
((
flags
&
PyBUF_FORMAT
)
==
PyBUF_FORMAT
)
{
view
->
format
=
const_cast
<
char
*>
(
info
->
format
.
c_str
());
}
if
((
flags
&
PyBUF_STRIDES
)
==
PyBUF_STRIDES
)
{
view
->
ndim
=
(
int
)
info
->
ndim
;
view
->
strides
=
info
->
strides
.
data
();
...
...
@@ -608,10 +632,11 @@ inline PyObject* make_new_python_type(const type_record &rec) {
object
module_
;
if
(
rec
.
scope
)
{
if
(
hasattr
(
rec
.
scope
,
"__module__"
))
if
(
hasattr
(
rec
.
scope
,
"__module__"
))
{
module_
=
rec
.
scope
.
attr
(
"__module__"
);
else
if
(
hasattr
(
rec
.
scope
,
"__name__"
))
}
else
if
(
hasattr
(
rec
.
scope
,
"__name__"
))
{
module_
=
rec
.
scope
.
attr
(
"__name__"
);
}
}
auto
full_name
=
c_str
(
...
...
@@ -642,8 +667,9 @@ inline PyObject* make_new_python_type(const type_record &rec) {
:
internals
.
default_metaclass
;
auto
heap_type
=
(
PyHeapTypeObject
*
)
metaclass
->
tp_alloc
(
metaclass
,
0
);
if
(
!
heap_type
)
if
(
!
heap_type
)
{
pybind11_fail
(
std
::
string
(
rec
.
name
)
+
": Unable to create type object!"
);
}
heap_type
->
ht_name
=
name
.
release
().
ptr
();
#ifdef PYBIND11_BUILTIN_QUALNAME
...
...
@@ -655,8 +681,9 @@ inline PyObject* make_new_python_type(const type_record &rec) {
type
->
tp_doc
=
tp_doc
;
type
->
tp_base
=
type_incref
((
PyTypeObject
*
)
base
);
type
->
tp_basicsize
=
static_cast
<
ssize_t
>
(
sizeof
(
instance
));
if
(
!
bases
.
empty
())
if
(
!
bases
.
empty
())
{
type
->
tp_bases
=
bases
.
release
().
ptr
();
}
/* Don't inherit base __init__ */
type
->
tp_init
=
pybind11_object_init
;
...
...
@@ -674,31 +701,38 @@ inline PyObject* make_new_python_type(const type_record &rec) {
#if PY_MAJOR_VERSION < 3
type
->
tp_flags
|=
Py_TPFLAGS_CHECKTYPES
;
#endif
if
(
!
rec
.
is_final
)
if
(
!
rec
.
is_final
)
{
type
->
tp_flags
|=
Py_TPFLAGS_BASETYPE
;
}
if
(
rec
.
dynamic_attr
)
if
(
rec
.
dynamic_attr
)
{
enable_dynamic_attributes
(
heap_type
);
}
if
(
rec
.
buffer_protocol
)
if
(
rec
.
buffer_protocol
)
{
enable_buffer_protocol
(
heap_type
);
}
if
(
rec
.
custom_type_setup_callback
)
if
(
rec
.
custom_type_setup_callback
)
{
rec
.
custom_type_setup_callback
(
heap_type
);
}
if
(
PyType_Ready
(
type
)
<
0
)
if
(
PyType_Ready
(
type
)
<
0
)
{
pybind11_fail
(
std
::
string
(
rec
.
name
)
+
": PyType_Ready failed ("
+
error_string
()
+
")!"
);
}
assert
(
!
rec
.
dynamic_attr
||
PyType_HasFeature
(
type
,
Py_TPFLAGS_HAVE_GC
));
/* Register type with the parent scope */
if
(
rec
.
scope
)
if
(
rec
.
scope
)
{
setattr
(
rec
.
scope
,
rec
.
name
,
(
PyObject
*
)
type
);
else
}
else
{
Py_INCREF
(
type
);
// Keep it alive forever (reference leak)
}
if
(
module_
)
// Needed by pydoc
if
(
module_
)
{
// Needed by pydoc
setattr
((
PyObject
*
)
type
,
"__module__"
,
module_
);
}
PYBIND11_SET_OLDPY_QUALNAME
(
type
,
qualname
);
...
...
include/pybind11/detail/init.h
View file @
ddbc74c6
...
...
@@ -33,7 +33,9 @@ private:
PYBIND11_NAMESPACE_BEGIN
(
initimpl
)
inline
void
no_nullptr
(
void
*
ptr
)
{
if
(
!
ptr
)
throw
type_error
(
"pybind11::init(): factory function returned nullptr"
);
if
(
!
ptr
)
{
throw
type_error
(
"pybind11::init(): factory function returned nullptr"
);
}
}
// Implementing functions for all forms of py::init<...> and py::init(...)
...
...
@@ -136,9 +138,10 @@ void construct(value_and_holder &v_h, Holder<Class> holder, bool need_alias) {
auto
*
ptr
=
holder_helper
<
Holder
<
Class
>>::
get
(
holder
);
no_nullptr
(
ptr
);
// If we need an alias, check that the held pointer is actually an alias instance
if
(
PYBIND11_SILENCE_MSVC_C4127
(
Class
::
has_alias
)
&&
need_alias
&&
!
is_alias
<
Class
>
(
ptr
))
if
(
PYBIND11_SILENCE_MSVC_C4127
(
Class
::
has_alias
)
&&
need_alias
&&
!
is_alias
<
Class
>
(
ptr
))
{
throw
type_error
(
"pybind11::init(): construction failed: returned holder-wrapped instance "
"is not an alias instance"
);
}
v_h
.
value_ptr
()
=
ptr
;
v_h
.
type
->
init_instance
(
v_h
.
inst
,
&
holder
);
...
...
@@ -153,10 +156,11 @@ void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) {
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100
(
need_alias
);
static_assert
(
std
::
is_move_constructible
<
Cpp
<
Class
>>::
value
,
"pybind11::init() return-by-value factory function requires a movable class"
);
if
(
PYBIND11_SILENCE_MSVC_C4127
(
Class
::
has_alias
)
&&
need_alias
)
if
(
PYBIND11_SILENCE_MSVC_C4127
(
Class
::
has_alias
)
&&
need_alias
)
{
construct_alias_from_cpp
<
Class
>
(
is_alias_constructible
<
Class
>
{},
v_h
,
std
::
move
(
result
));
else
}
else
{
v_h
.
value_ptr
()
=
new
Cpp
<
Class
>
(
std
::
move
(
result
));
}
}
// return-by-value version 2: returning a value of the alias type itself. We move-construct an
...
...
@@ -183,12 +187,19 @@ struct constructor {
enable_if_t
<
Class
::
has_alias
&&
std
::
is_constructible
<
Cpp
<
Class
>,
Args
...
>::
value
,
int
>
=
0
>
static
void
execute
(
Class
&
cl
,
const
Extra
&
...
extra
)
{
cl
.
def
(
"__init__"
,
[](
value_and_holder
&
v_h
,
Args
...
args
)
{
if
(
Py_TYPE
(
v_h
.
inst
)
==
v_h
.
type
->
type
)
v_h
.
value_ptr
()
=
construct_or_initialize
<
Cpp
<
Class
>>
(
std
::
forward
<
Args
>
(
args
)...);
else
v_h
.
value_ptr
()
=
construct_or_initialize
<
Alias
<
Class
>>
(
std
::
forward
<
Args
>
(
args
)...);
},
is_new_style_constructor
(),
extra
...);
cl
.
def
(
"__init__"
,
[](
value_and_holder
&
v_h
,
Args
...
args
)
{
if
(
Py_TYPE
(
v_h
.
inst
)
==
v_h
.
type
->
type
)
{
v_h
.
value_ptr
()
=
construct_or_initialize
<
Cpp
<
Class
>>
(
std
::
forward
<
Args
>
(
args
)...);
}
else
{
v_h
.
value_ptr
()
=
construct_or_initialize
<
Alias
<
Class
>>
(
std
::
forward
<
Args
>
(
args
)...);
}
},
is_new_style_constructor
(),
extra
...);
}
template
<
typename
Class
,
typename
...
Extra
,
...
...
include/pybind11/detail/internals.h
View file @
ddbc74c6
...
...
@@ -398,8 +398,9 @@ inline void translate_local_exception(std::exception_ptr p) {
/// Return a reference to the current `internals` data
PYBIND11_NOINLINE
internals
&
get_internals
()
{
auto
**&
internals_pp
=
get_internals_pp
();
if
(
internals_pp
&&
*
internals_pp
)
if
(
internals_pp
&&
*
internals_pp
)
{
return
**
internals_pp
;
}
// Ensure that the GIL is held since we will need to make Python calls.
// Cannot use py::gil_scoped_acquire here since that constructor calls get_internals.
...
...
@@ -425,7 +426,9 @@ PYBIND11_NOINLINE internals &get_internals() {
(
*
internals_pp
)
->
registered_exception_translators
.
push_front
(
&
translate_local_exception
);
#endif
}
else
{
if
(
!
internals_pp
)
internals_pp
=
new
internals
*
();
if
(
!
internals_pp
)
{
internals_pp
=
new
internals
*
();
}
auto
*&
internals_ptr
=
*
internals_pp
;
internals_ptr
=
new
internals
();
#if defined(WITH_THREAD)
...
...
include/pybind11/detail/type_caster_base.h
View file @
ddbc74c6
...
...
@@ -69,11 +69,13 @@ public:
/// ... and destroyed after it returns
~
loader_life_support
()
{
if
(
get_stack_top
()
!=
this
)
if
(
get_stack_top
()
!=
this
)
{
pybind11_fail
(
"loader_life_support: internal error"
);
}
set_stack_top
(
parent
);
for
(
auto
*
item
:
keep_alive
)
for
(
auto
*
item
:
keep_alive
)
{
Py_DECREF
(
item
);
}
}
/// This can only be used inside a pybind11-bound function, either by `argument_loader`
...
...
@@ -90,8 +92,9 @@ public:
"of temporary values"
);
}
if
(
frame
->
keep_alive
.
insert
(
h
.
ptr
()).
second
)
if
(
frame
->
keep_alive
.
insert
(
h
.
ptr
()).
second
)
{
Py_INCREF
(
h
.
ptr
());
}
}
};
...
...
@@ -103,14 +106,17 @@ inline std::pair<decltype(internals::registered_types_py)::iterator, bool> all_t
// Populates a just-created cache entry.
PYBIND11_NOINLINE
void
all_type_info_populate
(
PyTypeObject
*
t
,
std
::
vector
<
type_info
*>
&
bases
)
{
std
::
vector
<
PyTypeObject
*>
check
;
for
(
handle
parent
:
reinterpret_borrow
<
tuple
>
(
t
->
tp_bases
))
for
(
handle
parent
:
reinterpret_borrow
<
tuple
>
(
t
->
tp_bases
))
{
check
.
push_back
((
PyTypeObject
*
)
parent
.
ptr
());
}
auto
const
&
type_dict
=
get_internals
().
registered_types_py
;
for
(
size_t
i
=
0
;
i
<
check
.
size
();
i
++
)
{
auto
type
=
check
[
i
];
// Ignore Python2 old-style class super type:
if
(
!
PyType_Check
((
PyObject
*
)
type
))
continue
;
if
(
!
PyType_Check
((
PyObject
*
)
type
))
{
continue
;
}
// Check `type` in the current set of registered python types:
auto
it
=
type_dict
.
find
(
type
);
...
...
@@ -127,7 +133,9 @@ PYBIND11_NOINLINE void all_type_info_populate(PyTypeObject *t, std::vector<type_
for
(
auto
*
known
:
bases
)
{
if
(
known
==
tinfo
)
{
found
=
true
;
break
;
}
}
if
(
!
found
)
bases
.
push_back
(
tinfo
);
if
(
!
found
)
{
bases
.
push_back
(
tinfo
);
}
}
}
else
if
(
type
->
tp_bases
)
{
...
...
@@ -140,8 +148,9 @@ PYBIND11_NOINLINE void all_type_info_populate(PyTypeObject *t, std::vector<type_
check
.
pop_back
();
i
--
;
}
for
(
handle
parent
:
reinterpret_borrow
<
tuple
>
(
type
->
tp_bases
))
for
(
handle
parent
:
reinterpret_borrow
<
tuple
>
(
type
->
tp_bases
))
{
check
.
push_back
((
PyTypeObject
*
)
parent
.
ptr
());
}
}
}
}
...
...
@@ -158,9 +167,10 @@ PYBIND11_NOINLINE void all_type_info_populate(PyTypeObject *t, std::vector<type_
*/
inline
const
std
::
vector
<
detail
::
type_info
*>
&
all_type_info
(
PyTypeObject
*
type
)
{
auto
ins
=
all_type_info_get_cache
(
type
);
if
(
ins
.
second
)
if
(
ins
.
second
)
{
// New cache entry: populate it
all_type_info_populate
(
type
,
ins
.
first
->
second
);
}
return
ins
.
first
->
second
;
}
...
...
@@ -172,36 +182,43 @@ inline const std::vector<detail::type_info *> &all_type_info(PyTypeObject *type)
*/
PYBIND11_NOINLINE
detail
::
type_info
*
get_type_info
(
PyTypeObject
*
type
)
{
auto
&
bases
=
all_type_info
(
type
);
if
(
bases
.
empty
())
if
(
bases
.
empty
())
{
return
nullptr
;
if
(
bases
.
size
()
>
1
)
pybind11_fail
(
"pybind11::detail::get_type_info: type has multiple pybind11-registered bases"
);
}
if
(
bases
.
size
()
>
1
)
{
pybind11_fail
(
"pybind11::detail::get_type_info: type has multiple pybind11-registered bases"
);
}
return
bases
.
front
();
}
inline
detail
::
type_info
*
get_local_type_info
(
const
std
::
type_index
&
tp
)
{
auto
&
locals
=
get_local_internals
().
registered_types_cpp
;
auto
it
=
locals
.
find
(
tp
);
if
(
it
!=
locals
.
end
())
if
(
it
!=
locals
.
end
())
{
return
it
->
second
;
}
return
nullptr
;
}
inline
detail
::
type_info
*
get_global_type_info
(
const
std
::
type_index
&
tp
)
{
auto
&
types
=
get_internals
().
registered_types_cpp
;
auto
it
=
types
.
find
(
tp
);
if
(
it
!=
types
.
end
())
if
(
it
!=
types
.
end
())
{
return
it
->
second
;
}
return
nullptr
;
}
/// Return the type info for a given C++ type; on lookup failure can either throw or return nullptr.
PYBIND11_NOINLINE
detail
::
type_info
*
get_type_info
(
const
std
::
type_index
&
tp
,
bool
throw_if_missing
=
false
)
{
if
(
auto
ltype
=
get_local_type_info
(
tp
))
if
(
auto
ltype
=
get_local_type_info
(
tp
))
{
return
ltype
;
if
(
auto
gtype
=
get_global_type_info
(
tp
))
}
if
(
auto
gtype
=
get_global_type_info
(
tp
))
{
return
gtype
;
}
if
(
throw_if_missing
)
{
std
::
string
tname
=
tp
.
name
();
...
...
@@ -222,8 +239,9 @@ PYBIND11_NOINLINE handle find_registered_python_instance(void *src,
auto
it_instances
=
get_internals
().
registered_instances
.
equal_range
(
src
);
for
(
auto
it_i
=
it_instances
.
first
;
it_i
!=
it_instances
.
second
;
++
it_i
)
{
for
(
auto
instance_type
:
detail
::
all_type_info
(
Py_TYPE
(
it_i
->
second
)))
{
if
(
instance_type
&&
same_type
(
*
instance_type
->
cpptype
,
*
tinfo
->
cpptype
))
if
(
instance_type
&&
same_type
(
*
instance_type
->
cpptype
,
*
tinfo
->
cpptype
))
{
return
handle
((
PyObject
*
)
it_i
->
second
).
inc_ref
();
}
}
}
return
handle
();
...
...
@@ -263,12 +281,13 @@ struct value_and_holder {
}
// NOLINTNEXTLINE(readability-make-member-function-const)
void
set_holder_constructed
(
bool
v
=
true
)
{
if
(
inst
->
simple_layout
)
if
(
inst
->
simple_layout
)
{
inst
->
simple_holder_constructed
=
v
;
else
if
(
v
)
}
else
if
(
v
)
{
inst
->
nonsimple
.
status
[
index
]
|=
instance
::
status_holder_constructed
;
else
}
else
{
inst
->
nonsimple
.
status
[
index
]
&=
(
std
::
uint8_t
)
~
instance
::
status_holder_constructed
;
}
}
bool
instance_registered
()
const
{
return
inst
->
simple_layout
...
...
@@ -277,12 +296,13 @@ struct value_and_holder {
}
// NOLINTNEXTLINE(readability-make-member-function-const)
void
set_instance_registered
(
bool
v
=
true
)
{
if
(
inst
->
simple_layout
)
if
(
inst
->
simple_layout
)
{
inst
->
simple_instance_registered
=
v
;
else
if
(
v
)
}
else
if
(
v
)
{
inst
->
nonsimple
.
status
[
index
]
|=
instance
::
status_instance_registered
;
else
}
else
{
inst
->
nonsimple
.
status
[
index
]
&=
(
std
::
uint8_t
)
~
instance
::
status_instance_registered
;
}
}
};
...
...
@@ -317,8 +337,9 @@ public:
bool
operator
==
(
const
iterator
&
other
)
const
{
return
curr
.
index
==
other
.
curr
.
index
;
}
bool
operator
!=
(
const
iterator
&
other
)
const
{
return
curr
.
index
!=
other
.
curr
.
index
;
}
iterator
&
operator
++
()
{
if
(
!
inst
->
simple_layout
)
if
(
!
inst
->
simple_layout
)
{
curr
.
vh
+=
1
+
(
*
types
)[
curr
.
index
]
->
holder_size_in_ptrs
;
}
++
curr
.
index
;
curr
.
type
=
curr
.
index
<
types
->
size
()
?
(
*
types
)[
curr
.
index
]
:
nullptr
;
return
*
this
;
...
...
@@ -332,7 +353,9 @@ public:
iterator
find
(
const
type_info
*
find_type
)
{
auto
it
=
begin
(),
endit
=
end
();
while
(
it
!=
endit
&&
it
->
type
!=
find_type
)
++
it
;
while
(
it
!=
endit
&&
it
->
type
!=
find_type
)
{
++
it
;
}
return
it
;
}
...
...
@@ -351,16 +374,19 @@ public:
*/
PYBIND11_NOINLINE
value_and_holder
instance
::
get_value_and_holder
(
const
type_info
*
find_type
/*= nullptr default in common.h*/
,
bool
throw_if_missing
/*= true in common.h*/
)
{
// Optimize common case:
if
(
!
find_type
||
Py_TYPE
(
this
)
==
find_type
->
type
)
if
(
!
find_type
||
Py_TYPE
(
this
)
==
find_type
->
type
)
{
return
value_and_holder
(
this
,
find_type
,
0
,
0
);
}
detail
::
values_and_holders
vhs
(
this
);
auto
it
=
vhs
.
find
(
find_type
);
if
(
it
!=
vhs
.
end
())
if
(
it
!=
vhs
.
end
())
{
return
*
it
;
}
if
(
!
throw_if_missing
)
if
(
!
throw_if_missing
)
{
return
value_and_holder
();
}
#if defined(NDEBUG)
pybind11_fail
(
"pybind11::detail::instance::get_value_and_holder: "
...
...
@@ -378,8 +404,10 @@ PYBIND11_NOINLINE void instance::allocate_layout() {
const
size_t
n_types
=
tinfo
.
size
();
if
(
n_types
==
0
)
pybind11_fail
(
"instance allocation failed: new instance has no pybind11-registered base types"
);
if
(
n_types
==
0
)
{
pybind11_fail
(
"instance allocation failed: new instance has no pybind11-registered base types"
);
}
simple_layout
=
n_types
==
1
&&
tinfo
.
front
()
->
holder_size_in_ptrs
<=
instance_simple_holder_in_ptrs
();
...
...
@@ -410,7 +438,9 @@ PYBIND11_NOINLINE void instance::allocate_layout() {
// just wrappers around malloc.
#if PY_VERSION_HEX >= 0x03050000
nonsimple
.
values_and_holders
=
(
void
**
)
PyMem_Calloc
(
space
,
sizeof
(
void
*
));
if
(
!
nonsimple
.
values_and_holders
)
throw
std
::
bad_alloc
();
if
(
!
nonsimple
.
values_and_holders
)
{
throw
std
::
bad_alloc
();
}
#else
nonsimple
.
values_and_holders
=
(
void
**
)
PyMem_New
(
void
*
,
space
);
if
(
!
nonsimple
.
values_and_holders
)
throw
std
::
bad_alloc
();
...
...
@@ -423,14 +453,16 @@ PYBIND11_NOINLINE void instance::allocate_layout() {
// NOLINTNEXTLINE(readability-make-member-function-const)
PYBIND11_NOINLINE
void
instance
::
deallocate_layout
()
{
if
(
!
simple_layout
)
if
(
!
simple_layout
)
{
PyMem_Free
(
nonsimple
.
values_and_holders
);
}
}
PYBIND11_NOINLINE
bool
isinstance_generic
(
handle
obj
,
const
std
::
type_info
&
tp
)
{
handle
type
=
detail
::
get_type_handle
(
tp
,
false
);
if
(
!
type
)
if
(
!
type
)
{
return
false
;
}
return
isinstance
(
obj
,
type
);
}
...
...
@@ -447,14 +479,16 @@ PYBIND11_NOINLINE std::string error_string() {
errorString
+=
handle
(
scope
.
type
).
attr
(
"__name__"
).
cast
<
std
::
string
>
();
errorString
+=
": "
;
}
if
(
scope
.
value
)
if
(
scope
.
value
)
{
errorString
+=
(
std
::
string
)
str
(
scope
.
value
);
}
PyErr_NormalizeException
(
&
scope
.
type
,
&
scope
.
value
,
&
scope
.
trace
);
#if PY_MAJOR_VERSION >= 3
if
(
scope
.
trace
!=
nullptr
)
if
(
scope
.
trace
!=
nullptr
)
{
PyException_SetTraceback
(
scope
.
value
,
scope
.
trace
);
}
#endif
#if !defined(PYPY_VERSION)
...
...
@@ -462,8 +496,9 @@ PYBIND11_NOINLINE std::string error_string() {
auto
*
trace
=
(
PyTracebackObject
*
)
scope
.
trace
;
/* Get the deepest trace possible */
while
(
trace
->
tb_next
)
while
(
trace
->
tb_next
)
{
trace
=
trace
->
tb_next
;
}
PyFrameObject
*
frame
=
trace
->
tb_frame
;
errorString
+=
"
\n\n
At:
\n
"
;
...
...
@@ -493,8 +528,9 @@ PYBIND11_NOINLINE handle get_object_handle(const void *ptr, const detail::type_i
auto
range
=
instances
.
equal_range
(
ptr
);
for
(
auto
it
=
range
.
first
;
it
!=
range
.
second
;
++
it
)
{
for
(
const
auto
&
vh
:
values_and_holders
(
it
->
second
))
{
if
(
vh
.
type
==
type
)
if
(
vh
.
type
==
type
)
{
return
handle
((
PyObject
*
)
it
->
second
);
}
}
}
return
handle
();
...
...
@@ -535,15 +571,18 @@ public:
void
*
(
*
copy_constructor
)(
const
void
*
),
void
*
(
*
move_constructor
)(
const
void
*
),
const
void
*
existing_holder
=
nullptr
)
{
if
(
!
tinfo
)
// no type info: error will be set already
if
(
!
tinfo
)
{
// no type info: error will be set already
return
handle
();
}
void
*
src
=
const_cast
<
void
*>
(
_src
);
if
(
src
==
nullptr
)
if
(
src
==
nullptr
)
{
return
none
().
release
();
}
if
(
handle
registered_inst
=
find_registered_python_instance
(
src
,
tinfo
))
if
(
handle
registered_inst
=
find_registered_python_instance
(
src
,
tinfo
))
{
return
registered_inst
;
}
auto
inst
=
reinterpret_steal
<
object
>
(
make_new_instance
(
tinfo
->
type
));
auto
wrapper
=
reinterpret_cast
<
instance
*>
(
inst
.
ptr
());
...
...
@@ -564,9 +603,9 @@ public:
break
;
case
return_value_policy
::
copy
:
if
(
copy_constructor
)
if
(
copy_constructor
)
{
valueptr
=
copy_constructor
(
src
);
else
{
}
else
{
#if defined(NDEBUG)
throw
cast_error
(
"return_value_policy = copy, but type is "
"non-copyable! (compile in debug mode for details)"
);
...
...
@@ -581,11 +620,11 @@ public:
break
;
case
return_value_policy
::
move
:
if
(
move_constructor
)
if
(
move_constructor
)
{
valueptr
=
move_constructor
(
src
);
else
if
(
copy_constructor
)
}
else
if
(
copy_constructor
)
{
valueptr
=
copy_constructor
(
src
);
else
{
}
else
{
#if defined(NDEBUG)
throw
cast_error
(
"return_value_policy = move, but type is neither "
"movable nor copyable! "
...
...
@@ -650,8 +689,9 @@ public:
}
bool
try_direct_conversions
(
handle
src
)
{
for
(
auto
&
converter
:
*
typeinfo
->
direct_conversions
)
{
if
(
converter
(
src
.
ptr
(),
value
))
if
(
converter
(
src
.
ptr
(),
value
))
{
return
true
;
}
}
return
false
;
}
...
...
@@ -659,8 +699,9 @@ public:
PYBIND11_NOINLINE
static
void
*
local_load
(
PyObject
*
src
,
const
type_info
*
ti
)
{
auto
caster
=
type_caster_generic
(
ti
);
if
(
caster
.
load
(
src
,
false
))
if
(
caster
.
load
(
src
,
false
))
{
return
caster
.
value
;
}
return
nullptr
;
}
...
...
@@ -669,14 +710,16 @@ public:
PYBIND11_NOINLINE
bool
try_load_foreign_module_local
(
handle
src
)
{
constexpr
auto
*
local_key
=
PYBIND11_MODULE_LOCAL_ID
;
const
auto
pytype
=
type
::
handle_of
(
src
);
if
(
!
hasattr
(
pytype
,
local_key
))
if
(
!
hasattr
(
pytype
,
local_key
))
{
return
false
;
}
type_info
*
foreign_typeinfo
=
reinterpret_borrow
<
capsule
>
(
getattr
(
pytype
,
local_key
));
// Only consider this foreign loader if actually foreign and is a loader of the correct cpp type
if
(
foreign_typeinfo
->
module_local_load
==
&
local_load
||
(
cpptype
&&
!
same_type
(
*
cpptype
,
*
foreign_typeinfo
->
cpptype
)))
||
(
cpptype
&&
!
same_type
(
*
cpptype
,
*
foreign_typeinfo
->
cpptype
)))
{
return
false
;
}
if
(
auto
result
=
foreign_typeinfo
->
module_local_load
(
src
.
ptr
(),
foreign_typeinfo
))
{
value
=
result
;
...
...
@@ -690,8 +733,12 @@ public:
// logic (without having to resort to virtual inheritance).
template
<
typename
ThisT
>
PYBIND11_NOINLINE
bool
load_impl
(
handle
src
,
bool
convert
)
{
if
(
!
src
)
return
false
;
if
(
!
typeinfo
)
return
try_load_foreign_module_local
(
src
);
if
(
!
src
)
{
return
false
;
}
if
(
!
typeinfo
)
{
return
try_load_foreign_module_local
(
src
);
}
auto
&
this_
=
static_cast
<
ThisT
&>
(
*
this
);
this_
.
check_holder_compat
();
...
...
@@ -734,8 +781,9 @@ public:
// Case 2c: C++ multiple inheritance is involved and we couldn't find an exact type match
// in the registered bases, above, so try implicit casting (needed for proper C++ casting
// when MI is involved).
if
(
this_
.
try_implicit_casts
(
src
,
convert
))
if
(
this_
.
try_implicit_casts
(
src
,
convert
))
{
return
true
;
}
}
// Perform an implicit conversion
...
...
@@ -747,8 +795,9 @@ public:
return
true
;
}
}
if
(
this_
.
try_direct_conversions
(
src
))
if
(
this_
.
try_direct_conversions
(
src
))
{
return
true
;
}
}
// Failed to match local typeinfo. Try again with global.
...
...
@@ -767,7 +816,9 @@ public:
// Custom converters didn't take None, now we convert None to nullptr.
if
(
src
.
is_none
())
{
// Defer accepting None to other overloads (if we aren't in convert mode):
if
(
!
convert
)
return
false
;
if
(
!
convert
)
{
return
false
;
}
value
=
nullptr
;
return
true
;
}
...
...
@@ -907,8 +958,10 @@ public:
explicit
type_caster_base
(
const
std
::
type_info
&
info
)
:
type_caster_generic
(
info
)
{
}
static
handle
cast
(
const
itype
&
src
,
return_value_policy
policy
,
handle
parent
)
{
if
(
policy
==
return_value_policy
::
automatic
||
policy
==
return_value_policy
::
automatic_reference
)
if
(
policy
==
return_value_policy
::
automatic
||
policy
==
return_value_policy
::
automatic_reference
)
{
policy
=
return_value_policy
::
copy
;
}
return
cast
(
&
src
,
policy
,
parent
);
}
...
...
@@ -960,7 +1013,12 @@ public:
// NOLINTNEXTLINE(google-explicit-constructor)
operator
itype
*
()
{
return
(
type
*
)
value
;
}
// NOLINTNEXTLINE(google-explicit-constructor)
operator
itype
&
()
{
if
(
!
value
)
throw
reference_cast_error
();
return
*
((
itype
*
)
value
);
}
operator
itype
&
()
{
if
(
!
value
)
{
throw
reference_cast_error
();
}
return
*
((
itype
*
)
value
);
}
protected:
using
Constructor
=
void
*
(
*
)(
const
void
*
);
...
...
include/pybind11/detail/typeid.h
View file @
ddbc74c6
...
...
@@ -24,7 +24,9 @@ PYBIND11_NAMESPACE_BEGIN(detail)
inline
void
erase_all
(
std
::
string
&
string
,
const
std
::
string
&
search
)
{
for
(
size_t
pos
=
0
;;)
{
pos
=
string
.
find
(
search
,
pos
);
if
(
pos
==
std
::
string
::
npos
)
break
;
if
(
pos
==
std
::
string
::
npos
)
{
break
;
}
string
.
erase
(
pos
,
search
.
length
());
}
}
...
...
@@ -34,8 +36,9 @@ PYBIND11_NOINLINE void clean_type_id(std::string &name) {
int
status
=
0
;
std
::
unique_ptr
<
char
,
void
(
*
)(
void
*
)
>
res
{
abi
::
__cxa_demangle
(
name
.
c_str
(),
nullptr
,
nullptr
,
&
status
),
std
::
free
};
if
(
status
==
0
)
if
(
status
==
0
)
{
name
=
res
.
get
();
}
#else
detail
::
erase_all
(
name
,
"class "
);
detail
::
erase_all
(
name
,
"struct "
);
...
...
include/pybind11/eigen.h
View file @
ddbc74c6
...
...
@@ -145,8 +145,9 @@ template <typename Type_> struct EigenProps {
// (preferring the latter if it will fit in either, i.e. for a fully dynamic matrix type).
static
EigenConformable
<
row_major
>
conformable
(
const
array
&
a
)
{
const
auto
dims
=
a
.
ndim
();
if
(
dims
<
1
||
dims
>
2
)
if
(
dims
<
1
||
dims
>
2
)
{
return
false
;
}
if
(
dims
==
2
)
{
// Matrix type: require exact match (or dynamic)
...
...
@@ -155,9 +156,10 @@ template <typename Type_> struct EigenProps {
np_cols
=
a
.
shape
(
1
),
np_rstride
=
a
.
strides
(
0
)
/
static_cast
<
ssize_t
>
(
sizeof
(
Scalar
)),
np_cstride
=
a
.
strides
(
1
)
/
static_cast
<
ssize_t
>
(
sizeof
(
Scalar
));
if
((
PYBIND11_SILENCE_MSVC_C4127
(
fixed_rows
)
&&
np_rows
!=
rows
)
||
(
PYBIND11_SILENCE_MSVC_C4127
(
fixed_cols
)
&&
np_cols
!=
cols
))
if
((
PYBIND11_SILENCE_MSVC_C4127
(
fixed_rows
)
&&
np_rows
!=
rows
)
||
(
PYBIND11_SILENCE_MSVC_C4127
(
fixed_cols
)
&&
np_cols
!=
cols
))
{
return
false
;
}
return
{
np_rows
,
np_cols
,
np_rstride
,
np_cstride
};
}
...
...
@@ -168,8 +170,9 @@ template <typename Type_> struct EigenProps {
stride
=
a
.
strides
(
0
)
/
static_cast
<
ssize_t
>
(
sizeof
(
Scalar
));
if
(
vector
)
{
// Eigen type is a compile-time vector
if
(
PYBIND11_SILENCE_MSVC_C4127
(
fixed
)
&&
size
!=
n
)
if
(
PYBIND11_SILENCE_MSVC_C4127
(
fixed
)
&&
size
!=
n
)
{
return
false
;
// Vector size mismatch
}
return
{
rows
==
1
?
1
:
n
,
cols
==
1
?
1
:
n
,
stride
};
}
if
(
fixed
)
{
...
...
@@ -179,10 +182,14 @@ template <typename Type_> struct EigenProps {
if
(
fixed_cols
)
{
// Since this isn't a vector, cols must be != 1. We allow this only if it exactly
// equals the number of elements (rows is Dynamic, and so 1 row is allowed).
if
(
cols
!=
n
)
return
false
;
if
(
cols
!=
n
)
{
return
false
;
}
return
{
1
,
n
,
stride
};
}
// Otherwise it's either fully dynamic, or column dynamic; both become a column vector
if
(
PYBIND11_SILENCE_MSVC_C4127
(
fixed_rows
)
&&
rows
!=
n
)
return
false
;
if
(
PYBIND11_SILENCE_MSVC_C4127
(
fixed_rows
)
&&
rows
!=
n
)
{
return
false
;
}
return
{
n
,
1
,
stride
};
}
...
...
@@ -213,14 +220,18 @@ template <typename Type_> struct EigenProps {
template
<
typename
props
>
handle
eigen_array_cast
(
typename
props
::
Type
const
&
src
,
handle
base
=
handle
(),
bool
writeable
=
true
)
{
constexpr
ssize_t
elem_size
=
sizeof
(
typename
props
::
Scalar
);
array
a
;
if
(
props
::
vector
)
if
(
props
::
vector
)
{
a
=
array
({
src
.
size
()
},
{
elem_size
*
src
.
innerStride
()
},
src
.
data
(),
base
);
else
a
=
array
({
src
.
rows
(),
src
.
cols
()
},
{
elem_size
*
src
.
rowStride
(),
elem_size
*
src
.
colStride
()
},
src
.
data
(),
base
);
}
else
{
a
=
array
({
src
.
rows
(),
src
.
cols
()},
{
elem_size
*
src
.
rowStride
(),
elem_size
*
src
.
colStride
()},
src
.
data
(),
base
);
}
if
(
!
writeable
)
if
(
!
writeable
)
{
array_proxy
(
a
.
ptr
())
->
flags
&=
~
detail
::
npy_api
::
NPY_ARRAY_WRITEABLE_
;
}
return
a
.
release
();
}
...
...
@@ -255,28 +266,35 @@ struct type_caster<Type, enable_if_t<is_eigen_dense_plain<Type>::value>> {
bool
load
(
handle
src
,
bool
convert
)
{
// If we're in no-convert mode, only load if given an array of the correct type
if
(
!
convert
&&
!
isinstance
<
array_t
<
Scalar
>>
(
src
))
if
(
!
convert
&&
!
isinstance
<
array_t
<
Scalar
>>
(
src
))
{
return
false
;
}
// Coerce into an array, but don't do type conversion yet; the copy below handles it.
auto
buf
=
array
::
ensure
(
src
);
if
(
!
buf
)
if
(
!
buf
)
{
return
false
;
}
auto
dims
=
buf
.
ndim
();
if
(
dims
<
1
||
dims
>
2
)
if
(
dims
<
1
||
dims
>
2
)
{
return
false
;
}
auto
fits
=
props
::
conformable
(
buf
);
if
(
!
fits
)
if
(
!
fits
)
{
return
false
;
}
// Allocate the new type, then build a numpy reference into it
value
=
Type
(
fits
.
rows
,
fits
.
cols
);
auto
ref
=
reinterpret_steal
<
array
>
(
eigen_ref_array
<
props
>
(
value
));
if
(
dims
==
1
)
ref
=
ref
.
squeeze
();
else
if
(
ref
.
ndim
()
==
1
)
buf
=
buf
.
squeeze
();
if
(
dims
==
1
)
{
ref
=
ref
.
squeeze
();
}
else
if
(
ref
.
ndim
()
==
1
)
{
buf
=
buf
.
squeeze
();
}
int
result
=
detail
::
npy_api
::
get
().
PyArray_CopyInto_
(
ref
.
ptr
(),
buf
.
ptr
());
...
...
@@ -323,14 +341,18 @@ public:
}
// lvalue reference return; default (automatic) becomes copy
static
handle
cast
(
Type
&
src
,
return_value_policy
policy
,
handle
parent
)
{
if
(
policy
==
return_value_policy
::
automatic
||
policy
==
return_value_policy
::
automatic_reference
)
if
(
policy
==
return_value_policy
::
automatic
||
policy
==
return_value_policy
::
automatic_reference
)
{
policy
=
return_value_policy
::
copy
;
}
return
cast_impl
(
&
src
,
policy
,
parent
);
}
// const lvalue reference return; default (automatic) becomes copy
static
handle
cast
(
const
Type
&
src
,
return_value_policy
policy
,
handle
parent
)
{
if
(
policy
==
return_value_policy
::
automatic
||
policy
==
return_value_policy
::
automatic_reference
)
if
(
policy
==
return_value_policy
::
automatic
||
policy
==
return_value_policy
::
automatic_reference
)
{
policy
=
return_value_policy
::
copy
;
}
return
cast
(
&
src
,
policy
,
parent
);
}
// non-const pointer return
...
...
@@ -439,11 +461,14 @@ public:
if
(
aref
&&
(
!
need_writeable
||
aref
.
writeable
()))
{
fits
=
props
::
conformable
(
aref
);
if
(
!
fits
)
return
false
;
// Incompatible dimensions
if
(
!
fits
.
template
stride_compatible
<
props
>())
if
(
!
fits
)
{
return
false
;
// Incompatible dimensions
}
if
(
!
fits
.
template
stride_compatible
<
props
>())
{
need_copy
=
true
;
else
}
else
{
copy_or_ref
=
std
::
move
(
aref
);
}
}
else
{
need_copy
=
true
;
...
...
@@ -454,13 +479,18 @@ public:
// We need to copy: If we need a mutable reference, or we're not supposed to convert
// (either because we're in the no-convert overload pass, or because we're explicitly
// instructed not to copy (via `py::arg().noconvert()`) we have to fail loading.
if
(
!
convert
||
need_writeable
)
return
false
;
if
(
!
convert
||
need_writeable
)
{
return
false
;
}
Array
copy
=
Array
::
ensure
(
src
);
if
(
!
copy
)
return
false
;
if
(
!
copy
)
{
return
false
;
}
fits
=
props
::
conformable
(
copy
);
if
(
!
fits
||
!
fits
.
template
stride_compatible
<
props
>())
if
(
!
fits
||
!
fits
.
template
stride_compatible
<
props
>())
{
return
false
;
}
copy_or_ref
=
std
::
move
(
copy
);
loader_life_support
::
add_patient
(
copy_or_ref
);
}
...
...
@@ -550,8 +580,9 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
static
constexpr
bool
rowMajor
=
Type
::
IsRowMajor
;
bool
load
(
handle
src
,
bool
)
{
if
(
!
src
)
if
(
!
src
)
{
return
false
;
}
auto
obj
=
reinterpret_borrow
<
object
>
(
src
);
object
sparse_module
=
module_
::
import
(
"scipy.sparse"
);
...
...
@@ -572,8 +603,9 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
auto
shape
=
pybind11
::
tuple
((
pybind11
::
object
)
obj
.
attr
(
"shape"
));
auto
nnz
=
obj
.
attr
(
"nnz"
).
cast
<
Index
>
();
if
(
!
values
||
!
innerIndices
||
!
outerIndices
)
if
(
!
values
||
!
innerIndices
||
!
outerIndices
)
{
return
false
;
}
value
=
EigenMapSparseMatrix
<
Scalar
,
Type
::
Flags
&
(
Eigen
::
RowMajor
|
Eigen
::
ColMajor
),
...
...
include/pybind11/embed.h
View file @
ddbc74c6
...
...
@@ -77,12 +77,14 @@ struct embedded_module {
using
init_t
=
void
(
*
)();
#endif
embedded_module
(
const
char
*
name
,
init_t
init
)
{
if
(
Py_IsInitialized
()
!=
0
)
if
(
Py_IsInitialized
()
!=
0
)
{
pybind11_fail
(
"Can't add new modules after the interpreter has been initialized"
);
}
auto
result
=
PyImport_AppendInittab
(
name
,
init
);
if
(
result
==
-
1
)
if
(
result
==
-
1
)
{
pybind11_fail
(
"Insufficient memory to add a new module"
);
}
}
};
...
...
@@ -135,8 +137,9 @@ inline void set_interpreter_argv(int argc, const char *const *argv, bool add_pro
const
char
*
const
empty_argv
[]{
"
\0
"
};
const
char
*
const
*
safe_argv
=
special_case
?
empty_argv
:
argv
;
if
(
special_case
)
if
(
special_case
)
{
argc
=
1
;
}
auto
argv_size
=
static_cast
<
size_t
>
(
argc
);
#if PY_MAJOR_VERSION >= 3
...
...
@@ -192,8 +195,9 @@ inline void initialize_interpreter(bool init_signal_handlers = true,
int
argc
=
0
,
const
char
*
const
*
argv
=
nullptr
,
bool
add_program_dir_to_path
=
true
)
{
if
(
Py_IsInitialized
()
!=
0
)
if
(
Py_IsInitialized
()
!=
0
)
{
pybind11_fail
(
"The interpreter is already running"
);
}
Py_InitializeEx
(
init_signal_handlers
?
1
:
0
);
...
...
@@ -244,8 +248,9 @@ inline void finalize_interpreter() {
// during destruction), so we get the pointer-pointer here and check it after Py_Finalize().
detail
::
internals
**
internals_ptr_ptr
=
detail
::
get_internals_pp
();
// It could also be stashed in builtins, so look there too:
if
(
builtins
.
contains
(
id
)
&&
isinstance
<
capsule
>
(
builtins
[
id
]))
if
(
builtins
.
contains
(
id
)
&&
isinstance
<
capsule
>
(
builtins
[
id
]))
{
internals_ptr_ptr
=
capsule
(
builtins
[
id
]);
}
Py_Finalize
();
...
...
@@ -285,8 +290,9 @@ public:
scoped_interpreter
&
operator
=
(
scoped_interpreter
&&
)
=
delete
;
~
scoped_interpreter
()
{
if
(
is_valid
)
if
(
is_valid
)
{
finalize_interpreter
();
}
}
private:
...
...
include/pybind11/eval.h
View file @
ddbc74c6
...
...
@@ -46,8 +46,9 @@ enum eval_mode {
template
<
eval_mode
mode
=
eval_expr
>
object
eval
(
const
str
&
expr
,
object
global
=
globals
(),
object
local
=
object
())
{
if
(
!
local
)
if
(
!
local
)
{
local
=
global
;
}
detail
::
ensure_builtins_in_globals
(
global
);
...
...
@@ -64,8 +65,9 @@ object eval(const str &expr, object global = globals(), object local = object())
}
PyObject
*
result
=
PyRun_String
(
buffer
.
c_str
(),
start
,
global
.
ptr
(),
local
.
ptr
());
if
(
!
result
)
if
(
!
result
)
{
throw
error_already_set
();
}
return
reinterpret_steal
<
object
>
(
result
);
}
...
...
@@ -102,8 +104,9 @@ object eval_file(str) {
#else
template
<
eval_mode
mode
=
eval_statements
>
object
eval_file
(
str
fname
,
object
global
=
globals
(),
object
local
=
object
())
{
if
(
!
local
)
if
(
!
local
)
{
local
=
global
;
}
detail
::
ensure_builtins_in_globals
(
global
);
...
...
@@ -154,8 +157,9 @@ object eval_file(str fname, object global = globals(), object local = object())
local
.
ptr
(),
closeFile
);
#endif
if
(
!
result
)
if
(
!
result
)
{
throw
error_already_set
();
}
return
reinterpret_steal
<
object
>
(
result
);
}
#endif
...
...
include/pybind11/functional.h
View file @
ddbc74c6
...
...
@@ -25,12 +25,15 @@ public:
bool
load
(
handle
src
,
bool
convert
)
{
if
(
src
.
is_none
())
{
// Defer accepting None to other overloads (if we aren't in convert mode):
if
(
!
convert
)
return
false
;
if
(
!
convert
)
{
return
false
;
}
return
true
;
}
if
(
!
isinstance
<
function
>
(
src
))
if
(
!
isinstance
<
function
>
(
src
))
{
return
false
;
}
auto
func
=
reinterpret_borrow
<
function
>
(
src
);
...
...
@@ -104,12 +107,14 @@ public:
template
<
typename
Func
>
static
handle
cast
(
Func
&&
f_
,
return_value_policy
policy
,
handle
/* parent */
)
{
if
(
!
f_
)
if
(
!
f_
)
{
return
none
().
inc_ref
();
}
auto
result
=
f_
.
template
target
<
function_type
>();
if
(
result
)
if
(
result
)
{
return
cpp_function
(
*
result
,
policy
).
release
();
}
return
cpp_function
(
std
::
forward
<
Func
>
(
f_
),
policy
).
release
();
}
...
...
include/pybind11/gil.h
View file @
ddbc74c6
...
...
@@ -99,8 +99,9 @@ public:
pybind11_fail
(
"scoped_acquire::dec_ref(): internal error!"
);
#endif
PyThreadState_Clear
(
tstate
);
if
(
active
)
if
(
active
)
{
PyThreadState_DeleteCurrent
();
}
PYBIND11_TLS_DELETE_VALUE
(
detail
::
get_internals
().
tstate
);
release
=
false
;
}
...
...
@@ -117,8 +118,9 @@ public:
PYBIND11_NOINLINE
~
gil_scoped_acquire
()
{
dec_ref
();
if
(
release
)
PyEval_SaveThread
();
if
(
release
)
{
PyEval_SaveThread
();
}
}
private:
PyThreadState
*
tstate
=
nullptr
;
...
...
@@ -150,11 +152,13 @@ public:
}
~
gil_scoped_release
()
{
if
(
!
tstate
)
if
(
!
tstate
)
{
return
;
}
// `PyEval_RestoreThread()` should not be called if runtime is finalizing
if
(
active
)
if
(
active
)
{
PyEval_RestoreThread
(
tstate
);
}
if
(
disassoc
)
{
auto
key
=
detail
::
get_internals
().
tstate
;
PYBIND11_TLS_REPLACE_VALUE
(
key
,
tstate
);
...
...
include/pybind11/iostream.h
View file @
ddbc74c6
...
...
@@ -71,23 +71,26 @@ private:
return
static_cast
<
unsigned
char
>
(
c
)
<=
0xEF
;
};
// If the last character is ASCII, there are no incomplete code points
if
(
is_ascii
(
*
rpptr
))
if
(
is_ascii
(
*
rpptr
))
{
return
0
;
}
// Otherwise, work back from the end of the buffer and find the first
// UTF-8 leading byte
const
auto
rpend
=
rbase
-
rpptr
>=
3
?
rpptr
+
3
:
rbase
;
const
auto
leading
=
std
::
find_if
(
rpptr
,
rpend
,
is_leading
);
if
(
leading
==
rbase
)
if
(
leading
==
rbase
)
{
return
0
;
}
const
auto
dist
=
static_cast
<
size_t
>
(
leading
-
rpptr
);
size_t
remainder
=
0
;
if
(
dist
==
0
)
if
(
dist
==
0
)
{
remainder
=
1
;
// 1-byte code point is impossible
else
if
(
dist
==
1
)
}
else
if
(
dist
==
1
)
{
remainder
=
is_leading_2b
(
*
leading
)
?
0
:
dist
+
1
;
else
if
(
dist
==
2
)
}
else
if
(
dist
==
2
)
{
remainder
=
is_leading_3b
(
*
leading
)
?
0
:
dist
+
1
;
}
// else if (dist >= 3), at least 4 bytes before encountering an UTF-8
// leading byte, either no remainder or invalid UTF-8.
// Invalid UTF-8 will cause an exception later when converting
...
...
@@ -110,8 +113,9 @@ private:
}
// Copy the remainder at the end of the buffer to the beginning:
if
(
remainder
>
0
)
if
(
remainder
>
0
)
{
std
::
memmove
(
pbase
(),
pptr
()
-
remainder
,
remainder
);
}
setp
(
pbase
(),
epptr
());
pbump
(
static_cast
<
int
>
(
remainder
));
}
...
...
@@ -223,10 +227,12 @@ public:
:
do_stdout_
(
do_stdout
),
do_stderr_
(
do_stderr
)
{}
void
enter
()
{
if
(
do_stdout_
)
if
(
do_stdout_
)
{
redirect_stdout
.
reset
(
new
scoped_ostream_redirect
());
if
(
do_stderr_
)
}
if
(
do_stderr_
)
{
redirect_stderr
.
reset
(
new
scoped_estream_redirect
());
}
}
void
exit
()
{
...
...
include/pybind11/numpy.h
View file @
ddbc74c6
...
...
@@ -87,10 +87,12 @@ struct numpy_internals {
numpy_type_info
*
get_type_info
(
const
std
::
type_info
&
tinfo
,
bool
throw_if_missing
=
true
)
{
auto
it
=
registered_dtypes
.
find
(
std
::
type_index
(
tinfo
));
if
(
it
!=
registered_dtypes
.
end
())
if
(
it
!=
registered_dtypes
.
end
())
{
return
&
(
it
->
second
);
if
(
throw_if_missing
)
}
if
(
throw_if_missing
)
{
pybind11_fail
(
std
::
string
(
"NumPy type info missing for "
)
+
tinfo
.
name
());
}
return
nullptr
;
}
...
...
@@ -105,8 +107,9 @@ PYBIND11_NOINLINE void load_numpy_internals(numpy_internals* &ptr) {
inline
numpy_internals
&
get_numpy_internals
()
{
static
numpy_internals
*
ptr
=
nullptr
;
if
(
!
ptr
)
if
(
!
ptr
)
{
load_numpy_internals
(
ptr
);
}
return
*
ptr
;
}
...
...
@@ -235,8 +238,9 @@ private:
npy_api
api
;
#define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func];
DECL_NPY_API
(
PyArray_GetNDArrayCFeatureVersion
);
if
(
api
.
PyArray_GetNDArrayCFeatureVersion_
()
<
0x7
)
if
(
api
.
PyArray_GetNDArrayCFeatureVersion_
()
<
0x7
)
{
pybind11_fail
(
"pybind11 numpy support requires numpy >= 1.7.0"
);
}
DECL_NPY_API
(
PyArray_Type
);
DECL_NPY_API
(
PyVoidArrType_Type
);
DECL_NPY_API
(
PyArrayDescr_Type
);
...
...
@@ -491,8 +495,9 @@ public:
/// This is essentially the same as calling numpy.dtype(args) in Python.
static
dtype
from_args
(
object
args
)
{
PyObject
*
ptr
=
nullptr
;
if
((
detail
::
npy_api
::
get
().
PyArray_DescrConverter_
(
args
.
ptr
(),
&
ptr
)
==
0
)
||
!
ptr
)
if
((
detail
::
npy_api
::
get
().
PyArray_DescrConverter_
(
args
.
ptr
(),
&
ptr
)
==
0
)
||
!
ptr
)
{
throw
error_already_set
();
}
return
reinterpret_steal
<
dtype
>
(
ptr
);
}
...
...
@@ -536,8 +541,9 @@ private:
dtype
strip_padding
(
ssize_t
itemsize
)
{
// Recursively strip all void fields with empty names that are generated for
// padding fields (as of NumPy v1.11).
if
(
!
has_fields
())
if
(
!
has_fields
())
{
return
*
this
;
}
struct
field_descr
{
PYBIND11_STR_TYPE
name
;
object
format
;
pybind11
::
int_
offset
;
};
std
::
vector
<
field_descr
>
field_descriptors
;
...
...
@@ -547,8 +553,9 @@ private:
auto
name
=
spec
[
0
].
cast
<
pybind11
::
str
>
();
auto
format
=
spec
[
1
].
cast
<
tuple
>
()[
0
].
cast
<
dtype
>
();
auto
offset
=
spec
[
1
].
cast
<
tuple
>
()[
1
].
cast
<
pybind11
::
int_
>
();
if
((
len
(
name
)
==
0u
)
&&
format
.
kind
()
==
'V'
)
if
((
len
(
name
)
==
0u
)
&&
format
.
kind
()
==
'V'
)
{
continue
;
}
field_descriptors
.
push_back
({(
PYBIND11_STR_TYPE
)
name
,
format
.
strip_padding
(
format
.
itemsize
()),
offset
});
}
...
...
@@ -586,22 +593,25 @@ public:
array
(
const
pybind11
::
dtype
&
dt
,
ShapeContainer
shape
,
StridesContainer
strides
,
const
void
*
ptr
=
nullptr
,
handle
base
=
handle
())
{
if
(
strides
->
empty
())
if
(
strides
->
empty
())
{
*
strides
=
detail
::
c_strides
(
*
shape
,
dt
.
itemsize
());
}
auto
ndim
=
shape
->
size
();
if
(
ndim
!=
strides
->
size
())
if
(
ndim
!=
strides
->
size
())
{
pybind11_fail
(
"NumPy: shape ndim doesn't match strides ndim"
);
}
auto
descr
=
dt
;
int
flags
=
0
;
if
(
base
&&
ptr
)
{
if
(
isinstance
<
array
>
(
base
))
if
(
isinstance
<
array
>
(
base
))
{
/* Copy flags from base (except ownership bit) */
flags
=
reinterpret_borrow
<
array
>
(
base
).
flags
()
&
~
detail
::
npy_api
::
NPY_ARRAY_OWNDATA_
;
else
}
else
{
/* Writable by default, easy to downgrade later on if needed */
flags
=
detail
::
npy_api
::
NPY_ARRAY_WRITEABLE_
;
}
}
auto
&
api
=
detail
::
npy_api
::
get
();
...
...
@@ -611,8 +621,9 @@ public:
reinterpret_cast
<
Py_intptr_t
*>
(
shape
->
data
()),
reinterpret_cast
<
Py_intptr_t
*>
(
strides
->
data
()),
const_cast
<
void
*>
(
ptr
),
flags
,
nullptr
));
if
(
!
tmp
)
if
(
!
tmp
)
{
throw
error_already_set
();
}
if
(
ptr
)
{
if
(
base
)
{
api
.
PyArray_SetBaseObject_
(
tmp
.
ptr
(),
base
.
inc_ref
().
ptr
());
...
...
@@ -681,8 +692,9 @@ public:
/// Dimension along a given axis
ssize_t
shape
(
ssize_t
dim
)
const
{
if
(
dim
>=
ndim
())
if
(
dim
>=
ndim
())
{
fail_dim_check
(
dim
,
"invalid axis"
);
}
return
shape
()[
dim
];
}
...
...
@@ -693,8 +705,9 @@ public:
/// Stride along a given axis
ssize_t
strides
(
ssize_t
dim
)
const
{
if
(
dim
>=
ndim
())
if
(
dim
>=
ndim
())
{
fail_dim_check
(
dim
,
"invalid axis"
);
}
return
strides
()[
dim
];
}
...
...
@@ -730,8 +743,9 @@ public:
/// Byte offset from beginning of the array to a given index (full or partial).
/// May throw if the index would lead to out of bounds access.
template
<
typename
...
Ix
>
ssize_t
offset_at
(
Ix
...
index
)
const
{
if
((
ssize_t
)
sizeof
...(
index
)
>
ndim
())
if
((
ssize_t
)
sizeof
...(
index
)
>
ndim
())
{
fail_dim_check
(
sizeof
...(
index
),
"too many indices for an array"
);
}
return
byte_offset
(
ssize_t
(
index
)...);
}
...
...
@@ -750,9 +764,11 @@ public:
* and the caller must take care not to access invalid dimensions or dimension indices.
*/
template
<
typename
T
,
ssize_t
Dims
=
-
1
>
detail
::
unchecked_mutable_reference
<
T
,
Dims
>
mutable_unchecked
()
&
{
if
(
PYBIND11_SILENCE_MSVC_C4127
(
Dims
>=
0
)
&&
ndim
()
!=
Dims
)
throw
std
::
domain_error
(
"array has incorrect number of dimensions: "
+
std
::
to_string
(
ndim
())
+
"; expected "
+
std
::
to_string
(
Dims
));
if
(
PYBIND11_SILENCE_MSVC_C4127
(
Dims
>=
0
)
&&
ndim
()
!=
Dims
)
{
throw
std
::
domain_error
(
"array has incorrect number of dimensions: "
+
std
::
to_string
(
ndim
())
+
"; expected "
+
std
::
to_string
(
Dims
));
}
return
detail
::
unchecked_mutable_reference
<
T
,
Dims
>
(
mutable_data
(),
shape
(),
strides
(),
ndim
());
}
...
...
@@ -764,9 +780,11 @@ public:
* invalid dimensions or dimension indices.
*/
template
<
typename
T
,
ssize_t
Dims
=
-
1
>
detail
::
unchecked_reference
<
T
,
Dims
>
unchecked
()
const
&
{
if
(
PYBIND11_SILENCE_MSVC_C4127
(
Dims
>=
0
)
&&
ndim
()
!=
Dims
)
throw
std
::
domain_error
(
"array has incorrect number of dimensions: "
+
std
::
to_string
(
ndim
())
+
"; expected "
+
std
::
to_string
(
Dims
));
if
(
PYBIND11_SILENCE_MSVC_C4127
(
Dims
>=
0
)
&&
ndim
()
!=
Dims
)
{
throw
std
::
domain_error
(
"array has incorrect number of dimensions: "
+
std
::
to_string
(
ndim
())
+
"; expected "
+
std
::
to_string
(
Dims
));
}
return
detail
::
unchecked_reference
<
T
,
Dims
>
(
data
(),
shape
(),
strides
(),
ndim
());
}
...
...
@@ -789,7 +807,9 @@ public:
auto
new_array
=
reinterpret_steal
<
object
>
(
detail
::
npy_api
::
get
().
PyArray_Resize_
(
m_ptr
,
&
d
,
int
(
refcheck
),
-
1
)
);
if
(
!
new_array
)
throw
error_already_set
();
if
(
!
new_array
)
{
throw
error_already_set
();
}
if
(
isinstance
<
array
>
(
new_array
))
{
*
this
=
std
::
move
(
new_array
);
}
}
...
...
@@ -824,8 +844,9 @@ public:
/// In case of an error, nullptr is returned and the Python error is cleared.
static
array
ensure
(
handle
h
,
int
ExtraFlags
=
0
)
{
auto
result
=
reinterpret_steal
<
array
>
(
raw_array
(
h
.
ptr
(),
ExtraFlags
));
if
(
!
result
)
if
(
!
result
)
{
PyErr_Clear
();
}
return
result
;
}
...
...
@@ -843,8 +864,9 @@ protected:
}
void
check_writeable
()
const
{
if
(
!
writeable
())
if
(
!
writeable
())
{
throw
std
::
domain_error
(
"array is not writeable"
);
}
}
template
<
typename
...
Ix
>
void
check_dimensions
(
Ix
...
index
)
const
{
...
...
@@ -890,13 +912,19 @@ public:
PYBIND11_DEPRECATED
(
"Use array_t<T>::ensure() instead"
)
array_t
(
handle
h
,
bool
is_borrowed
)
:
array
(
raw_array_t
(
h
.
ptr
()),
stolen_t
{})
{
if
(
!
m_ptr
)
PyErr_Clear
();
if
(
!
is_borrowed
)
Py_XDECREF
(
h
.
ptr
());
if
(
!
m_ptr
)
{
PyErr_Clear
();
}
if
(
!
is_borrowed
)
{
Py_XDECREF
(
h
.
ptr
());
}
}
// NOLINTNEXTLINE(google-explicit-constructor)
array_t
(
const
object
&
o
)
:
array
(
raw_array_t
(
o
.
ptr
()),
stolen_t
{})
{
if
(
!
m_ptr
)
throw
error_already_set
();
if
(
!
m_ptr
)
{
throw
error_already_set
();
}
}
explicit
array_t
(
const
buffer_info
&
info
,
handle
base
=
handle
())
:
array
(
info
,
base
)
{
}
...
...
@@ -933,15 +961,17 @@ public:
// Reference to element at a given index
template
<
typename
...
Ix
>
const
T
&
at
(
Ix
...
index
)
const
{
if
((
ssize_t
)
sizeof
...(
index
)
!=
ndim
())
if
((
ssize_t
)
sizeof
...(
index
)
!=
ndim
())
{
fail_dim_check
(
sizeof
...(
index
),
"index dimension mismatch"
);
}
return
*
(
static_cast
<
const
T
*>
(
array
::
data
())
+
byte_offset
(
ssize_t
(
index
)...)
/
itemsize
());
}
// Mutable reference to element at a given index
template
<
typename
...
Ix
>
T
&
mutable_at
(
Ix
...
index
)
{
if
((
ssize_t
)
sizeof
...(
index
)
!=
ndim
())
if
((
ssize_t
)
sizeof
...(
index
)
!=
ndim
())
{
fail_dim_check
(
sizeof
...(
index
),
"index dimension mismatch"
);
}
return
*
(
static_cast
<
T
*>
(
array
::
mutable_data
())
+
byte_offset
(
ssize_t
(
index
)...)
/
itemsize
());
}
...
...
@@ -970,8 +1000,9 @@ public:
/// it). In case of an error, nullptr is returned and the Python error is cleared.
static
array_t
ensure
(
handle
h
)
{
auto
result
=
reinterpret_steal
<
array_t
>
(
raw_array_t
(
h
.
ptr
()));
if
(
!
result
)
if
(
!
result
)
{
PyErr_Clear
();
}
return
result
;
}
...
...
@@ -1032,8 +1063,9 @@ struct pyobject_caster<array_t<T, ExtraFlags>> {
using
type
=
array_t
<
T
,
ExtraFlags
>
;
bool
load
(
handle
src
,
bool
convert
)
{
if
(
!
convert
&&
!
type
::
check_
(
src
))
if
(
!
convert
&&
!
type
::
check_
(
src
))
{
return
false
;
}
value
=
type
::
ensure
(
src
);
return
static_cast
<
bool
>
(
value
);
}
...
...
@@ -1098,8 +1130,9 @@ public:
static
constexpr
int
value
=
values
[
detail
::
is_fmt_numeric
<
T
>::
index
];
static
pybind11
::
dtype
dtype
()
{
if
(
auto
ptr
=
npy_api
::
get
().
PyArray_DescrFromType_
(
value
))
if
(
auto
ptr
=
npy_api
::
get
().
PyArray_DescrFromType_
(
value
))
{
return
reinterpret_steal
<
pybind11
::
dtype
>
(
ptr
);
}
pybind11_fail
(
"Unsupported buffer format!"
);
}
};
...
...
@@ -1147,8 +1180,9 @@ PYBIND11_NOINLINE void register_structured_dtype(
bool
(
*
direct_converter
)(
PyObject
*
,
void
*&
))
{
auto
&
numpy_internals
=
get_numpy_internals
();
if
(
numpy_internals
.
get_type_info
(
tinfo
,
false
))
if
(
numpy_internals
.
get_type_info
(
tinfo
,
false
))
{
pybind11_fail
(
"NumPy: dtype is already registered"
);
}
// Use ordered fields because order matters as of NumPy 1.14:
// https://docs.scipy.org/doc/numpy/release.html#multiple-field-indexing-assignment-of-structured-arrays
...
...
@@ -1158,9 +1192,10 @@ PYBIND11_NOINLINE void register_structured_dtype(
list
names
,
formats
,
offsets
;
for
(
auto
&
field
:
ordered_fields
)
{
if
(
!
field
.
descr
)
pybind11_fail
(
std
::
string
(
"NumPy: unsupported field dtype: `"
)
+
field
.
name
+
"` @ "
+
tinfo
.
name
());
if
(
!
field
.
descr
)
{
pybind11_fail
(
std
::
string
(
"NumPy: unsupported field dtype: `"
)
+
field
.
name
+
"` @ "
+
tinfo
.
name
());
}
names
.
append
(
PYBIND11_STR_TYPE
(
field
.
name
));
formats
.
append
(
field
.
descr
);
offsets
.
append
(
pybind11
::
int_
(
field
.
offset
));
...
...
@@ -1186,21 +1221,24 @@ PYBIND11_NOINLINE void register_structured_dtype(
// isn't guaranteed to work due to https://github.com/numpy/numpy/issues/9049
oss
<<
"^T{"
;
for
(
auto
&
field
:
ordered_fields
)
{
if
(
field
.
offset
>
offset
)
if
(
field
.
offset
>
offset
)
{
oss
<<
(
field
.
offset
-
offset
)
<<
'x'
;
}
oss
<<
field
.
format
<<
':'
<<
field
.
name
<<
':'
;
offset
=
field
.
offset
+
field
.
size
;
}
if
(
itemsize
>
offset
)
if
(
itemsize
>
offset
)
{
oss
<<
(
itemsize
-
offset
)
<<
'x'
;
}
oss
<<
'}'
;
auto
format_str
=
oss
.
str
();
// Sanity check: verify that NumPy properly parses our buffer format string
auto
&
api
=
npy_api
::
get
();
auto
arr
=
array
(
buffer_info
(
nullptr
,
itemsize
,
format_str
,
1
));
if
(
!
api
.
PyArray_EquivTypes_
(
dtype_ptr
,
arr
.
dtype
().
ptr
()))
if
(
!
api
.
PyArray_EquivTypes_
(
dtype_ptr
,
arr
.
dtype
().
ptr
()))
{
pybind11_fail
(
"NumPy: invalid buffer descriptor!"
);
}
auto
tindex
=
std
::
type_index
(
tinfo
);
numpy_internals
.
registered_dtypes
[
tindex
]
=
{
dtype_ptr
,
format_str
};
...
...
@@ -1234,8 +1272,9 @@ private:
static
bool
direct_converter
(
PyObject
*
obj
,
void
*&
value
)
{
auto
&
api
=
npy_api
::
get
();
if
(
!
PyObject_TypeCheck
(
obj
,
api
.
PyVoidArrType_Type_
))
if
(
!
PyObject_TypeCheck
(
obj
,
api
.
PyVoidArrType_Type_
))
{
return
false
;
}
if
(
auto
descr
=
reinterpret_steal
<
object
>
(
api
.
PyArray_DescrFromScalar_
(
obj
)))
{
if
(
api
.
PyArray_EquivTypes_
(
dtype_ptr
(),
descr
.
ptr
()))
{
value
=
((
PyVoidScalarObject_Proxy
*
)
obj
)
->
obval
;
...
...
@@ -1363,12 +1402,14 @@ public:
m_common_iterator
()
{
// Manual copy to avoid conversion warning if using std::copy
for
(
size_t
i
=
0
;
i
<
shape
.
size
();
++
i
)
for
(
size_t
i
=
0
;
i
<
shape
.
size
();
++
i
)
{
m_shape
[
i
]
=
shape
[
i
];
}
container_type
strides
(
shape
.
size
());
for
(
size_t
i
=
0
;
i
<
N
;
++
i
)
for
(
size_t
i
=
0
;
i
<
N
;
++
i
)
{
init_common_iterator
(
buffers
[
i
],
shape
,
m_common_iterator
[
i
],
strides
);
}
}
multi_array_iterator
&
operator
++
()
{
...
...
@@ -1401,10 +1442,11 @@ private:
auto
strides_iter
=
strides
.
rbegin
();
while
(
buffer_shape_iter
!=
buffer
.
shape
.
rend
())
{
if
(
*
shape_iter
==
*
buffer_shape_iter
)
if
(
*
shape_iter
==
*
buffer_shape_iter
)
{
*
strides_iter
=
*
buffer_strides_iter
;
else
}
else
{
*
strides_iter
=
0
;
}
++
buffer_shape_iter
;
++
buffer_strides_iter
;
...
...
@@ -1417,8 +1459,9 @@ private:
}
void
increment_common_iterator
(
size_t
dim
)
{
for
(
auto
&
iter
:
m_common_iterator
)
for
(
auto
&
iter
:
m_common_iterator
)
{
iter
.
increment
(
dim
);
}
}
container_type
m_shape
;
...
...
@@ -1451,26 +1494,30 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, ssize_t &
auto
&
dim_size_out
=
*
res_iter
;
// Each input dimension can either be 1 or `n`, but `n` values must match across buffers
if
(
dim_size_out
==
1
)
if
(
dim_size_out
==
1
)
{
dim_size_out
=
dim_size_in
;
else
if
(
dim_size_in
!=
1
&&
dim_size_in
!=
dim_size_out
)
}
else
if
(
dim_size_in
!=
1
&&
dim_size_in
!=
dim_size_out
)
{
pybind11_fail
(
"pybind11::vectorize: incompatible size/dimension of inputs!"
);
}
}
}
bool
trivial_broadcast_c
=
true
;
bool
trivial_broadcast_f
=
true
;
for
(
size_t
i
=
0
;
i
<
N
&&
(
trivial_broadcast_c
||
trivial_broadcast_f
);
++
i
)
{
if
(
buffers
[
i
].
size
==
1
)
if
(
buffers
[
i
].
size
==
1
)
{
continue
;
}
// Require the same number of dimensions:
if
(
buffers
[
i
].
ndim
!=
ndim
)
if
(
buffers
[
i
].
ndim
!=
ndim
)
{
return
broadcast_trivial
::
non_trivial
;
}
// Require all dimensions be full-size:
if
(
!
std
::
equal
(
buffers
[
i
].
shape
.
cbegin
(),
buffers
[
i
].
shape
.
cend
(),
shape
.
cbegin
()))
if
(
!
std
::
equal
(
buffers
[
i
].
shape
.
cbegin
(),
buffers
[
i
].
shape
.
cend
(),
shape
.
cbegin
()))
{
return
broadcast_trivial
::
non_trivial
;
}
// Check for C contiguity (but only if previous inputs were also C contiguous)
if
(
trivial_broadcast_c
)
{
...
...
@@ -1478,10 +1525,11 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, ssize_t &
auto
end
=
buffers
[
i
].
shape
.
crend
();
for
(
auto
shape_iter
=
buffers
[
i
].
shape
.
crbegin
(),
stride_iter
=
buffers
[
i
].
strides
.
crbegin
();
trivial_broadcast_c
&&
shape_iter
!=
end
;
++
shape_iter
,
++
stride_iter
)
{
if
(
expect_stride
==
*
stride_iter
)
if
(
expect_stride
==
*
stride_iter
)
{
expect_stride
*=
*
shape_iter
;
else
}
else
{
trivial_broadcast_c
=
false
;
}
}
}
...
...
@@ -1491,10 +1539,11 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, ssize_t &
auto
end
=
buffers
[
i
].
shape
.
cend
();
for
(
auto
shape_iter
=
buffers
[
i
].
shape
.
cbegin
(),
stride_iter
=
buffers
[
i
].
strides
.
cbegin
();
trivial_broadcast_f
&&
shape_iter
!=
end
;
++
shape_iter
,
++
stride_iter
)
{
if
(
expect_stride
==
*
stride_iter
)
if
(
expect_stride
==
*
stride_iter
)
{
expect_stride
*=
*
shape_iter
;
else
}
else
{
trivial_broadcast_f
=
false
;
}
}
}
}
...
...
@@ -1527,8 +1576,9 @@ struct vectorize_returned_array {
using
Type
=
array_t
<
Return
>
;
static
Type
create
(
broadcast_trivial
trivial
,
const
std
::
vector
<
ssize_t
>
&
shape
)
{
if
(
trivial
==
broadcast_trivial
::
f_trivial
)
if
(
trivial
==
broadcast_trivial
::
f_trivial
)
{
return
array_t
<
Return
,
array
::
f_style
>
(
shape
);
}
return
array_t
<
Return
>
(
shape
);
}
...
...
@@ -1644,14 +1694,17 @@ private:
auto
result
=
returned_array
::
create
(
trivial
,
shape
);
if
(
size
==
0
)
return
std
::
move
(
result
);
if
(
size
==
0
)
{
return
std
::
move
(
result
);
}
/* Call the function */
auto
mutable_data
=
returned_array
::
mutable_data
(
result
);
if
(
trivial
==
broadcast_trivial
::
non_trivial
)
if
(
trivial
==
broadcast_trivial
::
non_trivial
)
{
apply_broadcast
(
buffers
,
params
,
mutable_data
,
size
,
shape
,
i_seq
,
vi_seq
,
bi_seq
);
else
}
else
{
apply_trivial
(
buffers
,
params
,
mutable_data
,
size
,
i_seq
,
vi_seq
,
bi_seq
);
}
return
std
::
move
(
result
);
}
...
...
@@ -1675,7 +1728,9 @@ private:
for
(
size_t
i
=
0
;
i
<
size
;
++
i
)
{
returned_array
::
call
(
out
,
i
,
f
,
*
reinterpret_cast
<
param_n_t
<
Index
>
*>
(
params
[
Index
])...);
for
(
auto
&
x
:
vecparams
)
x
.
first
+=
x
.
second
;
for
(
auto
&
x
:
vecparams
)
{
x
.
first
+=
x
.
second
;
}
}
}
...
...
include/pybind11/pybind11.h
View file @
ddbc74c6
...
...
@@ -212,8 +212,9 @@ protected:
cast_in
args_converter
;
/* Try to cast the function arguments into the C++ domain */
if
(
!
args_converter
.
load_args
(
call
))
if
(
!
args_converter
.
load_args
(
call
))
{
return
PYBIND11_TRY_NEXT_OVERLOAD
;
}
/* Invoke call policy pre-call hook */
process_attributes
<
Extra
...
>::
precall
(
call
);
...
...
@@ -286,8 +287,9 @@ protected:
class
strdup_guard
{
public:
~
strdup_guard
()
{
for
(
auto
s
:
strings
)
for
(
auto
s
:
strings
)
{
std
::
free
(
s
);
}
}
char
*
operator
()(
const
char
*
s
)
{
auto
t
=
PYBIND11_COMPAT_STRDUP
(
s
);
...
...
@@ -318,14 +320,18 @@ protected:
/* Create copies of all referenced C-style strings */
rec
->
name
=
guarded_strdup
(
rec
->
name
?
rec
->
name
:
""
);
if
(
rec
->
doc
)
rec
->
doc
=
guarded_strdup
(
rec
->
doc
);
if
(
rec
->
doc
)
{
rec
->
doc
=
guarded_strdup
(
rec
->
doc
);
}
for
(
auto
&
a
:
rec
->
args
)
{
if
(
a
.
name
)
if
(
a
.
name
)
{
a
.
name
=
guarded_strdup
(
a
.
name
);
if
(
a
.
descr
)
}
if
(
a
.
descr
)
{
a
.
descr
=
guarded_strdup
(
a
.
descr
);
else
if
(
a
.
value
)
}
else
if
(
a
.
value
)
{
a
.
descr
=
guarded_strdup
(
repr
(
a
.
value
).
cast
<
std
::
string
>
().
c_str
());
}
}
rec
->
is_constructor
=
(
std
::
strcmp
(
rec
->
name
,
"__init__"
)
==
0
)
...
...
@@ -355,12 +361,14 @@ protected:
if
(
c
==
'{'
)
{
// Write arg name for everything except *args and **kwargs.
is_starred
=
*
(
pc
+
1
)
==
'*'
;
if
(
is_starred
)
if
(
is_starred
)
{
continue
;
}
// Separator for keyword-only arguments, placed before the kw
// arguments start (unless we are already putting an *args)
if
(
!
rec
->
has_args
&&
arg_index
==
rec
->
nargs_pos
)
if
(
!
rec
->
has_args
&&
arg_index
==
rec
->
nargs_pos
)
{
signature
+=
"*, "
;
}
if
(
arg_index
<
rec
->
args
.
size
()
&&
rec
->
args
[
arg_index
].
name
)
{
signature
+=
rec
->
args
[
arg_index
].
name
;
}
else
if
(
arg_index
==
0
&&
rec
->
is_method
)
{
...
...
@@ -377,14 +385,17 @@ protected:
}
// Separator for positional-only arguments (placed after the
// argument, rather than before like *
if
(
rec
->
nargs_pos_only
>
0
&&
(
arg_index
+
1
)
==
rec
->
nargs_pos_only
)
if
(
rec
->
nargs_pos_only
>
0
&&
(
arg_index
+
1
)
==
rec
->
nargs_pos_only
)
{
signature
+=
", /"
;
if
(
!
is_starred
)
}
if
(
!
is_starred
)
{
arg_index
++
;
}
}
else
if
(
c
==
'%'
)
{
const
std
::
type_info
*
t
=
types
[
type_index
++
];
if
(
!
t
)
if
(
!
t
)
{
pybind11_fail
(
"Internal error while parsing type signature (1)"
);
}
if
(
auto
tinfo
=
detail
::
get_type_info
(
*
t
))
{
handle
th
((
PyObject
*
)
tinfo
->
type
);
signature
+=
...
...
@@ -406,8 +417,9 @@ protected:
}
}
if
(
arg_index
!=
args
-
rec
->
has_args
-
rec
->
has_kwargs
||
types
[
type_index
]
!=
nullptr
)
if
(
arg_index
!=
args
-
rec
->
has_args
-
rec
->
has_kwargs
||
types
[
type_index
]
!=
nullptr
)
{
pybind11_fail
(
"Internal error while parsing type signature (2)"
);
}
#if PY_MAJOR_VERSION < 3
if
(
std
::
strcmp
(
rec
->
name
,
"__next__"
)
==
0
)
{
...
...
@@ -422,8 +434,9 @@ protected:
rec
->
args
.
shrink_to_fit
();
rec
->
nargs
=
(
std
::
uint16_t
)
args
;
if
(
rec
->
sibling
&&
PYBIND11_INSTANCE_METHOD_CHECK
(
rec
->
sibling
.
ptr
()))
if
(
rec
->
sibling
&&
PYBIND11_INSTANCE_METHOD_CHECK
(
rec
->
sibling
.
ptr
()))
{
rec
->
sibling
=
PYBIND11_INSTANCE_METHOD_GET_FUNCTION
(
rec
->
sibling
.
ptr
());
}
detail
::
function_record
*
chain
=
nullptr
,
*
chain_start
=
rec
;
if
(
rec
->
sibling
)
{
...
...
@@ -433,13 +446,16 @@ protected:
chain
=
(
detail
::
function_record
*
)
rec_capsule
;
/* Never append a method to an overload chain of a parent class;
instead, hide the parent's overloads in this case */
if
(
!
chain
->
scope
.
is
(
rec
->
scope
))
if
(
!
chain
->
scope
.
is
(
rec
->
scope
))
{
chain
=
nullptr
;
}
}
// Don't trigger for things like the default __init__, which are wrapper_descriptors
// that we are intentionally replacing
else
if
(
!
rec
->
sibling
.
is_none
()
&&
rec
->
name
[
0
]
!=
'_'
)
{
pybind11_fail
(
"Cannot overload existing non-function object
\"
"
+
std
::
string
(
rec
->
name
)
+
"
\"
with a function of the same name"
);
}
// Don't trigger for things like the default __init__, which are wrapper_descriptors that we are intentionally replacing
else
if
(
!
rec
->
sibling
.
is_none
()
&&
rec
->
name
[
0
]
!=
'_'
)
pybind11_fail
(
"Cannot overload existing non-function object
\"
"
+
std
::
string
(
rec
->
name
)
+
"
\"
with a function of the same name"
);
}
if
(
!
chain
)
{
...
...
@@ -466,21 +482,26 @@ protected:
}
m_ptr
=
PyCFunction_NewEx
(
rec
->
def
,
rec_capsule
.
ptr
(),
scope_module
.
ptr
());
if
(
!
m_ptr
)
if
(
!
m_ptr
)
{
pybind11_fail
(
"cpp_function::cpp_function(): Could not allocate function object"
);
}
}
else
{
/* Append at the beginning or end of the overload chain */
m_ptr
=
rec
->
sibling
.
ptr
();
inc_ref
();
if
(
chain
->
is_method
!=
rec
->
is_method
)
pybind11_fail
(
"overloading a method with both static and instance methods is not supported; "
#if defined(NDEBUG)
"compile in debug mode for more details"
if
(
chain
->
is_method
!=
rec
->
is_method
)
{
pybind11_fail
(
"overloading a method with both static and instance methods is not supported; "
#if defined(NDEBUG)
"compile in debug mode for more details"
#else
"error while attempting to bind "
+
std
::
string
(
rec
->
is_method
?
"instance"
:
"static"
)
+
" method "
+
std
::
string
(
pybind11
::
str
(
rec
->
scope
.
attr
(
"__name__"
)))
+
"."
+
std
::
string
(
rec
->
name
)
+
signature
"error while attempting to bind "
+
std
::
string
(
rec
->
is_method
?
"instance"
:
"static"
)
+
" method "
+
std
::
string
(
pybind11
::
str
(
rec
->
scope
.
attr
(
"__name__"
)))
+
"."
+
std
::
string
(
rec
->
name
)
+
signature
#endif
);
}
if
(
rec
->
prepend
)
{
// Beginning of chain; we need to replace the capsule's current head-of-the-chain
...
...
@@ -494,8 +515,9 @@ protected:
}
else
{
// Or end of chain (normal behavior)
chain_start
=
chain
;
while
(
chain
->
next
)
while
(
chain
->
next
)
{
chain
=
chain
->
next
;
}
chain
->
next
=
unique_rec
.
release
();
guarded_strdup
.
release
();
}
...
...
@@ -515,9 +537,12 @@ protected:
bool
first_user_def
=
true
;
for
(
auto
it
=
chain_start
;
it
!=
nullptr
;
it
=
it
->
next
)
{
if
(
options
::
show_function_signatures
())
{
if
(
index
>
0
)
signatures
+=
"
\n
"
;
if
(
chain
)
if
(
index
>
0
)
{
signatures
+=
"
\n
"
;
}
if
(
chain
)
{
signatures
+=
std
::
to_string
(
++
index
)
+
". "
;
}
signatures
+=
rec
->
name
;
signatures
+=
it
->
signature
;
signatures
+=
"
\n
"
;
...
...
@@ -526,12 +551,19 @@ protected:
// If we're appending another docstring, and aren't printing function signatures, we
// need to append a newline first:
if
(
!
options
::
show_function_signatures
())
{
if
(
first_user_def
)
first_user_def
=
false
;
else
signatures
+=
"
\n
"
;
if
(
first_user_def
)
{
first_user_def
=
false
;
}
else
{
signatures
+=
"
\n
"
;
}
}
if
(
options
::
show_function_signatures
())
{
signatures
+=
"
\n
"
;
}
if
(
options
::
show_function_signatures
())
signatures
+=
"
\n
"
;
signatures
+=
it
->
doc
;
if
(
options
::
show_function_signatures
())
signatures
+=
"
\n
"
;
if
(
options
::
show_function_signatures
())
{
signatures
+=
"
\n
"
;
}
}
}
...
...
@@ -544,8 +576,10 @@ protected:
if
(
rec
->
is_method
)
{
m_ptr
=
PYBIND11_INSTANCE_METHOD_NEW
(
m_ptr
,
rec
->
scope
.
ptr
());
if
(
!
m_ptr
)
pybind11_fail
(
"cpp_function::cpp_function(): Could not allocate instance method object"
);
if
(
!
m_ptr
)
{
pybind11_fail
(
"cpp_function::cpp_function(): Could not allocate instance method object"
);
}
Py_DECREF
(
func
);
}
}
...
...
@@ -560,8 +594,9 @@ protected:
while
(
rec
)
{
detail
::
function_record
*
next
=
rec
->
next
;
if
(
rec
->
free_data
)
if
(
rec
->
free_data
)
{
rec
->
free_data
(
rec
);
}
// During initialization, these strings might not have been copied yet,
// so they cannot be freed. Once the function has been created, they can.
// Check `make_function_record` for more details.
...
...
@@ -574,17 +609,19 @@ protected:
std
::
free
(
const_cast
<
char
*>
(
arg
.
descr
));
}
}
for
(
auto
&
arg
:
rec
->
args
)
for
(
auto
&
arg
:
rec
->
args
)
{
arg
.
value
.
dec_ref
();
}
if
(
rec
->
def
)
{
std
::
free
(
const_cast
<
char
*>
(
rec
->
def
->
ml_doc
));
// Python 3.9.0 decref's these in the wrong order; rec->def
// If loaded on 3.9.0, let these leak (use Python 3.9.1 at runtime to fix)
// See https://github.com/python/cpython/pull/22670
#if !defined(PYPY_VERSION) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 9
if
(
!
is_zero
)
delete
rec
->
def
;
#else
if
(
!
is_zero
)
{
delete
rec
->
def
;
}
#else
delete
rec
->
def
;
#endif
}
...
...
@@ -621,8 +658,9 @@ protected:
// If this value is already registered it must mean __init__ is invoked multiple times;
// we really can't support that in C++, so just ignore the second __init__.
if
(
self_value_and_holder
.
instance_registered
())
if
(
self_value_and_holder
.
instance_registered
())
{
return
none
().
release
().
ptr
();
}
}
try
{
...
...
@@ -658,15 +696,22 @@ protected:
const
function_record
&
func
=
*
it
;
size_t
num_args
=
func
.
nargs
;
// Number of positional arguments that we need
if
(
func
.
has_args
)
--
num_args
;
// (but don't count py::args
if
(
func
.
has_kwargs
)
--
num_args
;
// or py::kwargs)
if
(
func
.
has_args
)
{
--
num_args
;
// (but don't count py::args
}
if
(
func
.
has_kwargs
)
{
--
num_args
;
// or py::kwargs)
}
size_t
pos_args
=
func
.
nargs_pos
;
if
(
!
func
.
has_args
&&
n_args_in
>
pos_args
)
if
(
!
func
.
has_args
&&
n_args_in
>
pos_args
)
{
continue
;
// Too many positional arguments for this overload
}
if
(
n_args_in
<
pos_args
&&
func
.
args
.
size
()
<
pos_args
)
continue
;
// Not enough positional arguments given, and not enough defaults to fill in the blanks
if
(
n_args_in
<
pos_args
&&
func
.
args
.
size
()
<
pos_args
)
{
continue
;
// Not enough positional arguments given, and not enough defaults to
// fill in the blanks
}
function_call
call
(
func
,
parent
);
...
...
@@ -677,8 +722,9 @@ protected:
if
(
func
.
is_new_style_constructor
)
{
// The `value` may have been preallocated by an old-style `__init__`
// if it was a preceding candidate for overload resolution.
if
(
self_value_and_holder
)
if
(
self_value_and_holder
)
{
self_value_and_holder
.
type
->
dealloc
(
self_value_and_holder
);
}
call
.
init_self
=
PyTuple_GET_ITEM
(
args_in
,
0
);
call
.
args
.
emplace_back
(
reinterpret_cast
<
PyObject
*>
(
&
self_value_and_holder
));
...
...
@@ -703,8 +749,9 @@ protected:
call
.
args
.
push_back
(
arg
);
call
.
args_convert
.
push_back
(
arg_rec
?
arg_rec
->
convert
:
true
);
}
if
(
bad_arg
)
if
(
bad_arg
)
{
continue
;
// Maybe it was meant for another overload (issue #688)
}
// Keep track of how many position args we copied out in case we need to come back
// to copy the rest into a py::args argument.
...
...
@@ -725,12 +772,14 @@ protected:
if
(
value
)
{
call
.
args
.
push_back
(
value
);
call
.
args_convert
.
push_back
(
arg_rec
.
convert
);
}
else
}
else
{
break
;
}
}
if
(
args_copied
<
func
.
nargs_pos_only
)
if
(
args_copied
<
func
.
nargs_pos_only
)
{
continue
;
// Not enough defaults to fill the positional arguments
}
}
// 2. Check kwargs and, failing that, defaults that may help complete the list
...
...
@@ -741,8 +790,9 @@ protected:
const
auto
&
arg_rec
=
func
.
args
[
args_copied
];
handle
value
;
if
(
kwargs_in
&&
arg_rec
.
name
)
if
(
kwargs_in
&&
arg_rec
.
name
)
{
value
=
dict_getitemstring
(
kwargs
.
ptr
(),
arg_rec
.
name
);
}
if
(
value
)
{
// Consume a kwargs value
...
...
@@ -763,23 +813,27 @@ protected:
if
(
value
)
{
// If we're at the py::args index then first insert a stub for it to be replaced later
if
(
func
.
has_args
&&
call
.
args
.
size
()
==
func
.
nargs_pos
)
if
(
func
.
has_args
&&
call
.
args
.
size
()
==
func
.
nargs_pos
)
{
call
.
args
.
push_back
(
none
());
}
call
.
args
.
push_back
(
value
);
call
.
args_convert
.
push_back
(
arg_rec
.
convert
);
}
else
}
else
{
break
;
}
}
if
(
args_copied
<
num_args
)
continue
;
// Not enough arguments, defaults, or kwargs to fill the positional arguments
if
(
args_copied
<
num_args
)
{
continue
;
// Not enough arguments, defaults, or kwargs to fill the
// positional arguments
}
}
// 3. Check everything was consumed (unless we have a kwargs arg)
if
(
kwargs
&&
!
kwargs
.
empty
()
&&
!
func
.
has_kwargs
)
if
(
kwargs
&&
!
kwargs
.
empty
()
&&
!
func
.
has_kwargs
)
{
continue
;
// Unconsumed kwargs, but no py::kwargs argument to accept them
}
// 4a. If we have a py::args argument, create a new tuple with leftovers
if
(
func
.
has_args
)
{
...
...
@@ -797,18 +851,20 @@ protected:
extra_args
[
i
]
=
PyTuple_GET_ITEM
(
args_in
,
positional_args_copied
+
i
);
}
}
if
(
call
.
args
.
size
()
<=
func
.
nargs_pos
)
if
(
call
.
args
.
size
()
<=
func
.
nargs_pos
)
{
call
.
args
.
push_back
(
extra_args
);
else
}
else
{
call
.
args
[
func
.
nargs_pos
]
=
extra_args
;
}
call
.
args_convert
.
push_back
(
false
);
call
.
args_ref
=
std
::
move
(
extra_args
);
}
// 4b. If we have a py::kwargs, pass on any remaining kwargs
if
(
func
.
has_kwargs
)
{
if
(
!
kwargs
.
ptr
())
if
(
!
kwargs
.
ptr
())
{
kwargs
=
dict
();
// If we didn't get one, send an empty one
}
call
.
args
.
push_back
(
kwargs
);
call
.
args_convert
.
push_back
(
false
);
call
.
kwargs_ref
=
std
::
move
(
kwargs
);
...
...
@@ -838,8 +894,9 @@ protected:
result
=
PYBIND11_TRY_NEXT_OVERLOAD
;
}
if
(
result
.
ptr
()
!=
PYBIND11_TRY_NEXT_OVERLOAD
)
if
(
result
.
ptr
()
!=
PYBIND11_TRY_NEXT_OVERLOAD
)
{
break
;
}
if
(
overloaded
)
{
// The (overloaded) call failed; if the call has at least one argument that
...
...
@@ -870,8 +927,9 @@ protected:
if
(
result
.
ptr
()
!=
PYBIND11_TRY_NEXT_OVERLOAD
)
{
// The error reporting logic below expects 'it' to be valid, as it would be
// if we'd encountered this failure in the first-pass loop.
if
(
!
result
)
if
(
!
result
)
{
it
=
&
call
.
func
;
}
break
;
}
}
...
...
@@ -923,8 +981,9 @@ protected:
};
if
(
result
.
ptr
()
==
PYBIND11_TRY_NEXT_OVERLOAD
)
{
if
(
overloads
->
is_operator
)
if
(
overloads
->
is_operator
)
{
return
handle
(
Py_NotImplemented
).
inc_ref
().
ptr
();
}
std
::
string
msg
=
std
::
string
(
overloads
->
name
)
+
"(): incompatible "
+
std
::
string
(
overloads
->
is_constructor
?
"constructor"
:
"function"
)
+
...
...
@@ -944,7 +1003,9 @@ protected:
size_t
end
=
sig
.
find
(
", "
),
next
=
end
+
2
;
size_t
ret
=
sig
.
rfind
(
" -> "
);
// Or the ), if there is no comma:
if
(
end
>=
sig
.
size
())
next
=
end
=
sig
.
find
(
')'
);
if
(
end
>=
sig
.
size
())
{
next
=
end
=
sig
.
find
(
')'
);
}
if
(
start
<
end
&&
next
<
sig
.
size
())
{
msg
.
append
(
sig
,
start
,
end
-
start
);
msg
+=
'('
;
...
...
@@ -953,7 +1014,9 @@ protected:
}
}
}
if
(
!
wrote_sig
)
msg
+=
it2
->
signature
;
if
(
!
wrote_sig
)
{
msg
+=
it2
->
signature
;
}
msg
+=
"
\n
"
;
}
...
...
@@ -961,8 +1024,11 @@ protected:
auto
args_
=
reinterpret_borrow
<
tuple
>
(
args_in
);
bool
some_args
=
false
;
for
(
size_t
ti
=
overloads
->
is_constructor
?
1
:
0
;
ti
<
args_
.
size
();
++
ti
)
{
if
(
!
some_args
)
some_args
=
true
;
else
msg
+=
", "
;
if
(
!
some_args
)
{
some_args
=
true
;
}
else
{
msg
+=
", "
;
}
try
{
msg
+=
pybind11
::
repr
(
args_
[
ti
]);
}
catch
(
const
error_already_set
&
)
{
...
...
@@ -972,12 +1038,17 @@ protected:
if
(
kwargs_in
)
{
auto
kwargs
=
reinterpret_borrow
<
dict
>
(
kwargs_in
);
if
(
!
kwargs
.
empty
())
{
if
(
some_args
)
msg
+=
"; "
;
if
(
some_args
)
{
msg
+=
"; "
;
}
msg
+=
"kwargs: "
;
bool
first
=
true
;
for
(
auto
kwarg
:
kwargs
)
{
if
(
first
)
first
=
false
;
else
msg
+=
", "
;
if
(
first
)
{
first
=
false
;
}
else
{
msg
+=
", "
;
}
msg
+=
pybind11
::
str
(
"{}="
).
format
(
kwarg
.
first
);
try
{
msg
+=
pybind11
::
repr
(
kwarg
.
second
);
...
...
@@ -1068,8 +1139,9 @@ public:
std
::
string
full_name
=
std
::
string
(
PyModule_GetName
(
m_ptr
))
+
std
::
string
(
"."
)
+
std
::
string
(
name
);
auto
result
=
reinterpret_borrow
<
module_
>
(
PyImport_AddModule
(
full_name
.
c_str
()));
if
(
doc
&&
options
::
show_user_defined_docstrings
())
if
(
doc
&&
options
::
show_user_defined_docstrings
())
{
result
.
attr
(
"__doc__"
)
=
pybind11
::
str
(
doc
);
}
attr
(
name
)
=
result
;
return
result
;
}
...
...
@@ -1077,16 +1149,18 @@ public:
/// Import and return a module or throws `error_already_set`.
static
module_
import
(
const
char
*
name
)
{
PyObject
*
obj
=
PyImport_ImportModule
(
name
);
if
(
!
obj
)
if
(
!
obj
)
{
throw
error_already_set
();
}
return
reinterpret_steal
<
module_
>
(
obj
);
}
/// Reload the module or throws `error_already_set`.
void
reload
()
{
PyObject
*
obj
=
PyImport_ReloadModule
(
ptr
());
if
(
!
obj
)
if
(
!
obj
)
{
throw
error_already_set
();
}
*
this
=
reinterpret_steal
<
module_
>
(
obj
);
}
...
...
@@ -1098,9 +1172,11 @@ public:
established will, in most cases, break things.
\endrst */
PYBIND11_NOINLINE
void
add_object
(
const
char
*
name
,
handle
obj
,
bool
overwrite
=
false
)
{
if
(
!
overwrite
&&
hasattr
(
*
this
,
name
))
pybind11_fail
(
"Error during initialization: multiple incompatible definitions with name
\"
"
+
std
::
string
(
name
)
+
"
\"
"
);
if
(
!
overwrite
&&
hasattr
(
*
this
,
name
))
{
pybind11_fail
(
"Error during initialization: multiple incompatible definitions with name
\"
"
+
std
::
string
(
name
)
+
"
\"
"
);
}
PyModule_AddObject
(
ptr
(),
name
,
obj
.
inc_ref
().
ptr
()
/* steals a reference */
);
}
...
...
@@ -1138,8 +1214,9 @@ public:
auto
m
=
Py_InitModule3
(
name
,
nullptr
,
options
::
show_user_defined_docstrings
()
?
doc
:
nullptr
);
#endif
if
(
m
==
nullptr
)
{
if
(
PyErr_Occurred
())
if
(
PyErr_Occurred
())
{
throw
error_already_set
();
}
pybind11_fail
(
"Internal error in module_::create_extension_module()"
);
}
// TODO: Should be reinterpret_steal for Python 3, but Python also steals it again when returned from PyInit_...
...
...
@@ -1177,14 +1254,17 @@ public:
PYBIND11_OBJECT_DEFAULT
(
generic_type
,
object
,
PyType_Check
)
protected:
void
initialize
(
const
type_record
&
rec
)
{
if
(
rec
.
scope
&&
hasattr
(
rec
.
scope
,
"__dict__"
)
&&
rec
.
scope
.
attr
(
"__dict__"
).
contains
(
rec
.
name
))
pybind11_fail
(
"generic_type: cannot initialize type
\"
"
+
std
::
string
(
rec
.
name
)
+
"
\"
: an object with that name is already defined"
);
if
(
rec
.
scope
&&
hasattr
(
rec
.
scope
,
"__dict__"
)
&&
rec
.
scope
.
attr
(
"__dict__"
).
contains
(
rec
.
name
))
{
pybind11_fail
(
"generic_type: cannot initialize type
\"
"
+
std
::
string
(
rec
.
name
)
+
"
\"
: an object with that name is already defined"
);
}
if
((
rec
.
module_local
?
get_local_type_info
(
*
rec
.
type
)
:
get_global_type_info
(
*
rec
.
type
))
!=
nullptr
)
pybind11_fail
(
"generic_type: type
\"
"
+
std
::
string
(
rec
.
name
)
+
"
\"
is already registered!"
);
!=
nullptr
)
{
pybind11_fail
(
"generic_type: type
\"
"
+
std
::
string
(
rec
.
name
)
+
"
\"
is already registered!"
);
}
m_ptr
=
make_new_python_type
(
rec
);
...
...
@@ -1206,10 +1286,11 @@ protected:
auto
&
internals
=
get_internals
();
auto
tindex
=
std
::
type_index
(
*
rec
.
type
);
tinfo
->
direct_conversions
=
&
internals
.
direct_conversions
[
tindex
];
if
(
rec
.
module_local
)
if
(
rec
.
module_local
)
{
get_local_internals
().
registered_types_cpp
[
tindex
]
=
tinfo
;
else
}
else
{
internals
.
registered_types_cpp
[
tindex
]
=
tinfo
;
}
internals
.
registered_types_py
[(
PyTypeObject
*
)
m_ptr
]
=
{
tinfo
};
if
(
rec
.
bases
.
size
()
>
1
||
rec
.
multiple_inheritance
)
{
...
...
@@ -1237,8 +1318,9 @@ protected:
auto
t
=
reinterpret_borrow
<
tuple
>
(
value
->
tp_bases
);
for
(
handle
h
:
t
)
{
auto
tinfo2
=
get_type_info
((
PyTypeObject
*
)
h
.
ptr
());
if
(
tinfo2
)
if
(
tinfo2
)
{
tinfo2
->
simple_type
=
false
;
}
mark_parents_nonsimple
((
PyTypeObject
*
)
h
.
ptr
());
}
}
...
...
@@ -1249,12 +1331,12 @@ protected:
auto
*
type
=
(
PyHeapTypeObject
*
)
m_ptr
;
auto
tinfo
=
detail
::
get_type_info
(
&
type
->
ht_type
);
if
(
!
type
->
ht_type
.
tp_as_buffer
)
pybind11_fail
(
"To be able to register buffer protocol support for the type '"
+
get_fully_qualified_tp_name
(
tinfo
->
type
)
+
"' the associated class<>(..) invocation must "
"include the pybind11::buffer_protocol() annotation!"
);
if
(
!
type
->
ht_type
.
tp_as_buffer
)
{
pybind11_fail
(
"To be able to register buffer protocol support for the type '"
+
get_fully_qualified_tp_name
(
tinfo
->
type
)
+
"' the associated class<>(..) invocation must "
"include the pybind11::buffer_protocol() annotation!"
);
}
tinfo
->
get_buffer
=
get_buffer
;
tinfo
->
get_buffer_data
=
get_buffer_data
;
...
...
@@ -1475,8 +1557,9 @@ public:
auto
*
ptr
=
new
capture
{
std
::
forward
<
Func
>
(
func
)
};
install_buffer_funcs
([](
PyObject
*
obj
,
void
*
ptr
)
->
buffer_info
*
{
detail
::
make_caster
<
type
>
caster
;
if
(
!
caster
.
load
(
obj
,
false
))
if
(
!
caster
.
load
(
obj
,
false
))
{
return
nullptr
;
}
return
new
buffer_info
(((
capture
*
)
ptr
)
->
func
(
caster
));
},
ptr
);
weakref
(
m_ptr
,
cpp_function
([
ptr
](
handle
wr
)
{
...
...
@@ -1598,7 +1681,9 @@ public:
std
::
free
(
doc_prev
);
rec_fset
->
doc
=
PYBIND11_COMPAT_STRDUP
(
rec_fset
->
doc
);
}
if
(
!
rec_active
)
rec_active
=
rec_fset
;
if
(
!
rec_active
)
{
rec_active
=
rec_fset
;
}
}
def_property_static_impl
(
name
,
fget
,
fset
,
rec_active
);
return
*
this
;
...
...
@@ -1716,8 +1801,9 @@ PYBIND11_NAMESPACE_BEGIN(detail)
inline
str
enum_name
(
handle
arg
)
{
dict
entries
=
arg
.
get_type
().
attr
(
"__entries"
);
for
(
auto
kv
:
entries
)
{
if
(
handle
(
kv
.
second
[
int_
(
0
)]).
equal
(
arg
))
if
(
handle
(
kv
.
second
[
int_
(
0
)]).
equal
(
arg
))
{
return
pybind11
::
str
(
kv
.
first
);
}
}
return
"???"
;
}
...
...
@@ -1752,15 +1838,17 @@ struct enum_base {
[](
handle
arg
)
->
std
::
string
{
std
::
string
docstring
;
dict
entries
=
arg
.
attr
(
"__entries"
);
if
(((
PyTypeObject
*
)
arg
.
ptr
())
->
tp_doc
)
if
(((
PyTypeObject
*
)
arg
.
ptr
())
->
tp_doc
)
{
docstring
+=
std
::
string
(((
PyTypeObject
*
)
arg
.
ptr
())
->
tp_doc
)
+
"
\n\n
"
;
}
docstring
+=
"Members:"
;
for
(
auto
kv
:
entries
)
{
auto
key
=
std
::
string
(
pybind11
::
str
(
kv
.
first
));
auto
comment
=
kv
.
second
[
int_
(
1
)];
docstring
+=
"
\n\n
"
+
key
;
if
(
!
comment
.
is_none
())
if
(
!
comment
.
is_none
())
{
docstring
+=
" : "
+
(
std
::
string
)
pybind11
::
str
(
comment
);
}
}
return
docstring
;
},
name
(
"__doc__"
)
...
...
@@ -1769,8 +1857,9 @@ struct enum_base {
m_base
.
attr
(
"__members__"
)
=
static_property
(
cpp_function
(
[](
handle
arg
)
->
dict
{
dict
entries
=
arg
.
attr
(
"__entries"
),
m
;
for
(
auto
kv
:
entries
)
for
(
auto
kv
:
entries
)
{
m
[
kv
.
first
]
=
kv
.
second
[
int_
(
0
)];
}
return
m
;
},
name
(
"__members__"
)),
none
(),
none
(),
""
);
...
...
@@ -1865,8 +1954,9 @@ struct enum_base {
PYBIND11_NOINLINE
void
export_values
()
{
dict
entries
=
m_base
.
attr
(
"__entries"
);
for
(
auto
kv
:
entries
)
for
(
auto
kv
:
entries
)
{
m_parent
.
attr
(
kv
.
first
)
=
kv
.
second
[
int_
(
0
)];
}
}
handle
m_base
;
...
...
@@ -1944,11 +2034,13 @@ PYBIND11_NAMESPACE_BEGIN(detail)
PYBIND11_NOINLINE
void
keep_alive_impl
(
handle
nurse
,
handle
patient
)
{
if
(
!
nurse
||
!
patient
)
if
(
!
nurse
||
!
patient
)
{
pybind11_fail
(
"Could not activate keep_alive!"
);
}
if
(
patient
.
is_none
()
||
nurse
.
is_none
())
if
(
patient
.
is_none
()
||
nurse
.
is_none
())
{
return
;
/* Nothing to keep alive or nothing to be kept alive by */
}
auto
tinfo
=
all_type_info
(
Py_TYPE
(
nurse
.
ptr
()));
if
(
!
tinfo
.
empty
())
{
...
...
@@ -1972,12 +2064,15 @@ PYBIND11_NOINLINE void keep_alive_impl(handle nurse, handle patient) {
PYBIND11_NOINLINE
void
keep_alive_impl
(
size_t
Nurse
,
size_t
Patient
,
function_call
&
call
,
handle
ret
)
{
auto
get_arg
=
[
&
](
size_t
n
)
{
if
(
n
==
0
)
if
(
n
==
0
)
{
return
ret
;
if
(
n
==
1
&&
call
.
init_self
)
}
if
(
n
==
1
&&
call
.
init_self
)
{
return
call
.
init_self
;
if
(
n
<=
call
.
args
.
size
())
}
if
(
n
<=
call
.
args
.
size
())
{
return
call
.
args
[
n
-
1
];
}
return
handle
();
};
...
...
@@ -2000,10 +2095,11 @@ inline std::pair<decltype(internals::registered_types_py)::iterator, bool> all_t
// TODO consolidate the erasure code in pybind11_meta_dealloc() in class.h
auto
&
cache
=
get_internals
().
inactive_override_cache
;
for
(
auto
it
=
cache
.
begin
(),
last
=
cache
.
end
();
it
!=
last
;
)
{
if
(
it
->
first
==
reinterpret_cast
<
PyObject
*>
(
type
))
if
(
it
->
first
==
reinterpret_cast
<
PyObject
*>
(
type
))
{
it
=
cache
.
erase
(
it
);
else
}
else
{
++
it
;
}
}
wr
.
dec_ref
();
...
...
@@ -2089,19 +2185,24 @@ iterator make_iterator_impl(Iterator first, Sentinel last, Extra &&... extra) {
if
(
!
detail
::
get_type_info
(
typeid
(
state
),
false
))
{
class_
<
state
>
(
handle
(),
"iterator"
,
pybind11
::
module_local
())
.
def
(
"__iter__"
,
[](
state
&
s
)
->
state
&
{
return
s
;
})
.
def
(
"__next__"
,
[](
state
&
s
)
->
ValueType
{
if
(
!
s
.
first_or_done
)
++
s
.
it
;
else
s
.
first_or_done
=
false
;
if
(
s
.
it
==
s
.
end
)
{
s
.
first_or_done
=
true
;
throw
stop_iteration
();
}
return
Access
()(
s
.
it
);
// NOLINTNEXTLINE(readability-const-return-type) // PR #3263
},
std
::
forward
<
Extra
>
(
extra
)...,
Policy
);
.
def
(
"__iter__"
,
[](
state
&
s
)
->
state
&
{
return
s
;
})
.
def
(
"__next__"
,
[](
state
&
s
)
->
ValueType
{
if
(
!
s
.
first_or_done
)
{
++
s
.
it
;
}
else
{
s
.
first_or_done
=
false
;
}
if
(
s
.
it
==
s
.
end
)
{
s
.
first_or_done
=
true
;
throw
stop_iteration
();
}
return
Access
()(
s
.
it
);
// NOLINTNEXTLINE(readability-const-return-type) // PR #3263
},
std
::
forward
<
Extra
>
(
extra
)...,
Policy
);
}
return
cast
(
state
{
first
,
last
,
true
});
...
...
@@ -2187,23 +2288,27 @@ template <typename InputType, typename OutputType> void implicitly_convertible()
};
auto
implicit_caster
=
[](
PyObject
*
obj
,
PyTypeObject
*
type
)
->
PyObject
*
{
static
bool
currently_used
=
false
;
if
(
currently_used
)
// implicit conversions are non-reentrant
if
(
currently_used
)
{
// implicit conversions are non-reentrant
return
nullptr
;
}
set_flag
flag_helper
(
currently_used
);
if
(
!
detail
::
make_caster
<
InputType
>
().
load
(
obj
,
false
))
if
(
!
detail
::
make_caster
<
InputType
>
().
load
(
obj
,
false
))
{
return
nullptr
;
}
tuple
args
(
1
);
args
[
0
]
=
obj
;
PyObject
*
result
=
PyObject_Call
((
PyObject
*
)
type
,
args
.
ptr
(),
nullptr
);
if
(
result
==
nullptr
)
if
(
result
==
nullptr
)
{
PyErr_Clear
();
}
return
result
;
};
if
(
auto
tinfo
=
detail
::
get_type_info
(
typeid
(
OutputType
)))
if
(
auto
tinfo
=
detail
::
get_type_info
(
typeid
(
OutputType
)))
{
tinfo
->
implicit_conversions
.
push_back
(
implicit_caster
);
else
}
else
{
pybind11_fail
(
"implicitly_convertible: Unable to find type "
+
type_id
<
OutputType
>
());
}
}
...
...
@@ -2239,9 +2344,11 @@ public:
std
::
string
full_name
=
scope
.
attr
(
"__name__"
).
cast
<
std
::
string
>
()
+
std
::
string
(
"."
)
+
name
;
m_ptr
=
PyErr_NewException
(
const_cast
<
char
*>
(
full_name
.
c_str
()),
base
.
ptr
(),
NULL
);
if
(
hasattr
(
scope
,
"__dict__"
)
&&
scope
.
attr
(
"__dict__"
).
contains
(
name
))
if
(
hasattr
(
scope
,
"__dict__"
)
&&
scope
.
attr
(
"__dict__"
).
contains
(
name
))
{
pybind11_fail
(
"Error during initialization: multiple incompatible "
"definitions with name
\"
"
+
std
::
string
(
name
)
+
"
\"
"
);
"definitions with name
\"
"
+
std
::
string
(
name
)
+
"
\"
"
);
}
scope
.
attr
(
name
)
=
*
this
;
}
...
...
@@ -2265,13 +2372,17 @@ exception<CppException> ®ister_exception_impl(handle scope,
handle
base
,
bool
isLocal
)
{
auto
&
ex
=
detail
::
get_exception_object
<
CppException
>
();
if
(
!
ex
)
ex
=
exception
<
CppException
>
(
scope
,
name
,
base
);
if
(
!
ex
)
{
ex
=
exception
<
CppException
>
(
scope
,
name
,
base
);
}
auto
register_func
=
isLocal
?
&
register_local_exception_translator
:
&
register_exception_translator
;
register_func
([](
std
::
exception_ptr
p
)
{
if
(
!
p
)
return
;
if
(
!
p
)
{
return
;
}
try
{
std
::
rethrow_exception
(
p
);
}
catch
(
const
CppException
&
e
)
{
...
...
@@ -2339,8 +2450,9 @@ PYBIND11_NOINLINE void print(const tuple &args, const dict &kwargs) {
write
(
line
);
write
(
kwargs
.
contains
(
"end"
)
?
kwargs
[
"end"
]
:
cast
(
"
\n
"
));
if
(
kwargs
.
contains
(
"flush"
)
&&
kwargs
[
"flush"
].
cast
<
bool
>
())
if
(
kwargs
.
contains
(
"flush"
)
&&
kwargs
[
"flush"
].
cast
<
bool
>
())
{
file
.
attr
(
"flush"
)();
}
}
PYBIND11_NAMESPACE_END
(
detail
)
...
...
@@ -2363,16 +2475,18 @@ error_already_set::~error_already_set() {
PYBIND11_NAMESPACE_BEGIN
(
detail
)
inline
function
get_type_override
(
const
void
*
this_ptr
,
const
type_info
*
this_type
,
const
char
*
name
)
{
handle
self
=
get_object_handle
(
this_ptr
,
this_type
);
if
(
!
self
)
if
(
!
self
)
{
return
function
();
}
handle
type
=
type
::
handle_of
(
self
);
auto
key
=
std
::
make_pair
(
type
.
ptr
(),
name
);
/* Cache functions that aren't overridden in Python to avoid
many costly Python dictionary lookups below */
auto
&
cache
=
get_internals
().
inactive_override_cache
;
if
(
cache
.
find
(
key
)
!=
cache
.
end
())
if
(
cache
.
find
(
key
)
!=
cache
.
end
())
{
return
function
();
}
function
override
=
getattr
(
self
,
name
,
function
());
if
(
override
.
is_cpp_function
())
{
...
...
include/pybind11/pytypes.h
View file @
ddbc74c6
...
...
@@ -242,7 +242,11 @@ class object : public handle {
public:
object
()
=
default
;
PYBIND11_DEPRECATED
(
"Use reinterpret_borrow<object>() or reinterpret_steal<object>()"
)
object
(
handle
h
,
bool
is_borrowed
)
:
handle
(
h
)
{
if
(
is_borrowed
)
inc_ref
();
}
object
(
handle
h
,
bool
is_borrowed
)
:
handle
(
h
)
{
if
(
is_borrowed
)
{
inc_ref
();
}
}
/// Copy constructor; always increases the reference count
object
(
const
object
&
o
)
:
handle
(
o
)
{
inc_ref
();
}
/// Move constructor; steals the object from ``other`` and preserves its reference count
...
...
@@ -458,8 +462,9 @@ template <> inline bool isinstance<object>(handle obj) { return obj.ptr() != nul
/// Return true if ``obj`` is an instance of the ``type``.
inline
bool
isinstance
(
handle
obj
,
handle
type
)
{
const
auto
result
=
PyObject_IsInstance
(
obj
.
ptr
(),
type
.
ptr
());
if
(
result
==
-
1
)
if
(
result
==
-
1
)
{
throw
error_already_set
();
}
return
result
!=
0
;
}
...
...
@@ -529,12 +534,13 @@ PYBIND11_NAMESPACE_BEGIN(detail)
inline
handle
get_function
(
handle
value
)
{
if
(
value
)
{
#if PY_MAJOR_VERSION >= 3
if
(
PyInstanceMethod_Check
(
value
.
ptr
()))
if
(
PyInstanceMethod_Check
(
value
.
ptr
()))
{
value
=
PyInstanceMethod_GET_FUNCTION
(
value
.
ptr
());
else
}
else
#endif
if
(
PyMethod_Check
(
value
.
ptr
()))
if
(
PyMethod_Check
(
value
.
ptr
()))
{
value
=
PyMethod_GET_FUNCTION
(
value
.
ptr
());
}
}
return
value
;
}
...
...
@@ -1076,14 +1082,18 @@ public:
template
<
typename
SzType
,
detail
::
enable_if_t
<
std
::
is_integral
<
SzType
>
::
value
,
int
>
=
0
>
str
(
const
char
*
c
,
const
SzType
&
n
)
:
object
(
PyUnicode_FromStringAndSize
(
c
,
ssize_t_cast
(
n
)),
stolen_t
{})
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate string object!"
);
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate string object!"
);
}
}
// 'explicit' is explicitly omitted from the following constructors to allow implicit conversion to py::str from C++ string-like objects
// NOLINTNEXTLINE(google-explicit-constructor)
str
(
const
char
*
c
=
""
)
:
object
(
PyUnicode_FromString
(
c
),
stolen_t
{})
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate string object!"
);
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate string object!"
);
}
}
// NOLINTNEXTLINE(google-explicit-constructor)
...
...
@@ -1109,20 +1119,26 @@ public:
Return a string representation of the object. This is analogous to
the ``str()`` function in Python.
\endrst */
explicit
str
(
handle
h
)
:
object
(
raw_str
(
h
.
ptr
()),
stolen_t
{})
{
if
(
!
m_ptr
)
throw
error_already_set
();
}
explicit
str
(
handle
h
)
:
object
(
raw_str
(
h
.
ptr
()),
stolen_t
{})
{
if
(
!
m_ptr
)
{
throw
error_already_set
();
}
}
// NOLINTNEXTLINE(google-explicit-constructor)
operator
std
::
string
()
const
{
object
temp
=
*
this
;
if
(
PyUnicode_Check
(
m_ptr
))
{
temp
=
reinterpret_steal
<
object
>
(
PyUnicode_AsUTF8String
(
m_ptr
));
if
(
!
temp
)
if
(
!
temp
)
{
throw
error_already_set
();
}
}
char
*
buffer
=
nullptr
;
ssize_t
length
=
0
;
if
(
PYBIND11_BYTES_AS_STRING_AND_SIZE
(
temp
.
ptr
(),
&
buffer
,
&
length
))
if
(
PYBIND11_BYTES_AS_STRING_AND_SIZE
(
temp
.
ptr
(),
&
buffer
,
&
length
))
{
pybind11_fail
(
"Unable to extract string contents! (invalid type)"
);
}
return
std
::
string
(
buffer
,
(
size_t
)
length
);
}
...
...
@@ -1162,13 +1178,17 @@ public:
// NOLINTNEXTLINE(google-explicit-constructor)
bytes
(
const
char
*
c
=
""
)
:
object
(
PYBIND11_BYTES_FROM_STRING
(
c
),
stolen_t
{})
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate bytes object!"
);
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate bytes object!"
);
}
}
template
<
typename
SzType
,
detail
::
enable_if_t
<
std
::
is_integral
<
SzType
>
::
value
,
int
>
=
0
>
bytes
(
const
char
*
c
,
const
SzType
&
n
)
:
object
(
PYBIND11_BYTES_FROM_STRING_AND_SIZE
(
c
,
ssize_t_cast
(
n
)),
stolen_t
{})
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate bytes object!"
);
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate bytes object!"
);
}
}
// Allow implicit conversion:
...
...
@@ -1181,8 +1201,9 @@ public:
operator
std
::
string
()
const
{
char
*
buffer
=
nullptr
;
ssize_t
length
=
0
;
if
(
PYBIND11_BYTES_AS_STRING_AND_SIZE
(
m_ptr
,
&
buffer
,
&
length
))
if
(
PYBIND11_BYTES_AS_STRING_AND_SIZE
(
m_ptr
,
&
buffer
,
&
length
))
{
pybind11_fail
(
"Unable to extract bytes contents!"
);
}
return
std
::
string
(
buffer
,
(
size_t
)
length
);
}
...
...
@@ -1199,8 +1220,9 @@ public:
operator
std
::
string_view
()
const
{
char
*
buffer
=
nullptr
;
ssize_t
length
=
0
;
if
(
PYBIND11_BYTES_AS_STRING_AND_SIZE
(
m_ptr
,
&
buffer
,
&
length
))
if
(
PYBIND11_BYTES_AS_STRING_AND_SIZE
(
m_ptr
,
&
buffer
,
&
length
))
{
pybind11_fail
(
"Unable to extract bytes contents!"
);
}
return
{
buffer
,
static_cast
<
size_t
>
(
length
)};
}
#endif
...
...
@@ -1214,27 +1236,32 @@ inline bytes::bytes(const pybind11::str &s) {
object
temp
=
s
;
if
(
PyUnicode_Check
(
s
.
ptr
()))
{
temp
=
reinterpret_steal
<
object
>
(
PyUnicode_AsUTF8String
(
s
.
ptr
()));
if
(
!
temp
)
if
(
!
temp
)
{
pybind11_fail
(
"Unable to extract string contents! (encoding issue)"
);
}
}
char
*
buffer
=
nullptr
;
ssize_t
length
=
0
;
if
(
PYBIND11_BYTES_AS_STRING_AND_SIZE
(
temp
.
ptr
(),
&
buffer
,
&
length
))
if
(
PYBIND11_BYTES_AS_STRING_AND_SIZE
(
temp
.
ptr
(),
&
buffer
,
&
length
))
{
pybind11_fail
(
"Unable to extract string contents! (invalid type)"
);
}
auto
obj
=
reinterpret_steal
<
object
>
(
PYBIND11_BYTES_FROM_STRING_AND_SIZE
(
buffer
,
length
));
if
(
!
obj
)
if
(
!
obj
)
{
pybind11_fail
(
"Could not allocate bytes object!"
);
}
m_ptr
=
obj
.
release
().
ptr
();
}
inline
str
::
str
(
const
bytes
&
b
)
{
char
*
buffer
=
nullptr
;
ssize_t
length
=
0
;
if
(
PYBIND11_BYTES_AS_STRING_AND_SIZE
(
b
.
ptr
(),
&
buffer
,
&
length
))
if
(
PYBIND11_BYTES_AS_STRING_AND_SIZE
(
b
.
ptr
(),
&
buffer
,
&
length
))
{
pybind11_fail
(
"Unable to extract bytes contents!"
);
}
auto
obj
=
reinterpret_steal
<
object
>
(
PyUnicode_FromStringAndSize
(
buffer
,
length
));
if
(
!
obj
)
if
(
!
obj
)
{
pybind11_fail
(
"Could not allocate string object!"
);
}
m_ptr
=
obj
.
release
().
ptr
();
}
...
...
@@ -1247,7 +1274,9 @@ public:
template
<
typename
SzType
,
detail
::
enable_if_t
<
std
::
is_integral
<
SzType
>
::
value
,
int
>
=
0
>
bytearray
(
const
char
*
c
,
const
SzType
&
n
)
:
object
(
PyByteArray_FromStringAndSize
(
c
,
ssize_t_cast
(
n
)),
stolen_t
{})
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate bytearray object!"
);
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate bytearray object!"
);
}
}
bytearray
()
...
...
@@ -1295,7 +1324,9 @@ private:
/// Return the truth value of an object -- always returns a new reference
static
PyObject
*
raw_bool
(
PyObject
*
op
)
{
const
auto
value
=
PyObject_IsTrue
(
op
);
if
(
value
==
-
1
)
return
nullptr
;
if
(
value
==
-
1
)
{
return
nullptr
;
}
return
handle
(
value
!=
0
?
Py_True
:
Py_False
).
inc_ref
().
ptr
();
}
};
...
...
@@ -1330,17 +1361,21 @@ public:
// NOLINTNEXTLINE(google-explicit-constructor)
int_
(
T
value
)
{
if
(
PYBIND11_SILENCE_MSVC_C4127
(
sizeof
(
T
)
<=
sizeof
(
long
)))
{
if
(
std
::
is_signed
<
T
>::
value
)
if
(
std
::
is_signed
<
T
>::
value
)
{
m_ptr
=
PyLong_FromLong
((
long
)
value
);
else
}
else
{
m_ptr
=
PyLong_FromUnsignedLong
((
unsigned
long
)
value
);
}
}
else
{
if
(
std
::
is_signed
<
T
>::
value
)
if
(
std
::
is_signed
<
T
>::
value
)
{
m_ptr
=
PyLong_FromLongLong
((
long
long
)
value
);
else
}
else
{
m_ptr
=
PyLong_FromUnsignedLongLong
((
unsigned
long
long
)
value
);
}
}
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate int object!"
);
}
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate int object!"
);
}
template
<
typename
T
,
...
...
@@ -1361,11 +1396,15 @@ public:
// Allow implicit conversion from float/double:
// NOLINTNEXTLINE(google-explicit-constructor)
float_
(
float
value
)
:
object
(
PyFloat_FromDouble
((
double
)
value
),
stolen_t
{})
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate float object!"
);
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate float object!"
);
}
}
// NOLINTNEXTLINE(google-explicit-constructor)
float_
(
double
value
=
.0
)
:
object
(
PyFloat_FromDouble
((
double
)
value
),
stolen_t
{})
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate float object!"
);
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate float object!"
);
}
}
// NOLINTNEXTLINE(google-explicit-constructor)
operator
float
()
const
{
return
(
float
)
PyFloat_AsDouble
(
m_ptr
);
}
...
...
@@ -1378,7 +1417,9 @@ public:
PYBIND11_OBJECT_CVT_DEFAULT
(
weakref
,
object
,
PyWeakref_Check
,
raw_weakref
)
explicit
weakref
(
handle
obj
,
handle
callback
=
{})
:
object
(
PyWeakref_NewRef
(
obj
.
ptr
(),
callback
.
ptr
()),
stolen_t
{})
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate weak reference!"
);
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate weak reference!"
);
}
}
private:
...
...
@@ -1392,8 +1433,9 @@ public:
PYBIND11_OBJECT_DEFAULT
(
slice
,
object
,
PySlice_Check
)
slice
(
handle
start
,
handle
stop
,
handle
step
)
{
m_ptr
=
PySlice_New
(
start
.
ptr
(),
stop
.
ptr
(),
step
.
ptr
());
if
(
!
m_ptr
)
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate slice object!"
);
}
}
#ifdef PYBIND11_HAS_OPTIONAL
...
...
@@ -1434,15 +1476,17 @@ public:
explicit
capsule
(
const
void
*
value
,
const
char
*
name
=
nullptr
,
void
(
*
destructor
)(
PyObject
*
)
=
nullptr
)
:
object
(
PyCapsule_New
(
const_cast
<
void
*>
(
value
),
name
,
destructor
),
stolen_t
{})
{
if
(
!
m_ptr
)
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate capsule object!"
);
}
}
PYBIND11_DEPRECATED
(
"Please pass a destructor that takes a void pointer as input"
)
capsule
(
const
void
*
value
,
void
(
*
destruct
)(
PyObject
*
))
:
object
(
PyCapsule_New
(
const_cast
<
void
*>
(
value
),
nullptr
,
destruct
),
stolen_t
{})
{
if
(
!
m_ptr
)
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate capsule object!"
);
}
}
capsule
(
const
void
*
value
,
void
(
*
destructor
)(
void
*
))
{
...
...
@@ -1452,11 +1496,13 @@ public:
destructor
(
ptr
);
});
if
(
!
m_ptr
)
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate capsule object!"
);
}
if
(
PyCapsule_SetContext
(
m_ptr
,
(
void
*
)
destructor
)
!=
0
)
if
(
PyCapsule_SetContext
(
m_ptr
,
(
void
*
)
destructor
)
!=
0
)
{
pybind11_fail
(
"Could not set capsule context!"
);
}
}
explicit
capsule
(
void
(
*
destructor
)())
{
...
...
@@ -1465,8 +1511,9 @@ public:
destructor
();
});
if
(
!
m_ptr
)
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate capsule object!"
);
}
}
// NOLINTNEXTLINE(google-explicit-constructor)
...
...
@@ -1504,7 +1551,9 @@ public:
detail
::
enable_if_t
<
std
::
is_integral
<
SzType
>
::
value
,
int
>
=
0
>
// Some compilers generate link errors when using `const SzType &` here:
explicit
tuple
(
SzType
size
=
0
)
:
object
(
PyTuple_New
(
ssize_t_cast
(
size
)),
stolen_t
{})
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate tuple object!"
);
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate tuple object!"
);
}
}
size_t
size
()
const
{
return
(
size_t
)
PyTuple_Size
(
m_ptr
);
}
bool
empty
()
const
{
return
size
()
==
0
;
}
...
...
@@ -1527,7 +1576,9 @@ class dict : public object {
public:
PYBIND11_OBJECT_CVT
(
dict
,
object
,
PyDict_Check
,
raw_dict
)
dict
()
:
object
(
PyDict_New
(),
stolen_t
{})
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate dict object!"
);
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate dict object!"
);
}
}
template
<
typename
...
Args
,
typename
=
detail
::
enable_if_t
<
args_are_all_keyword_or_ds
<
Args
...>()
>
,
...
...
@@ -1547,8 +1598,9 @@ public:
private:
/// Call the `dict` Python type -- always returns a new reference
static
PyObject
*
raw_dict
(
PyObject
*
op
)
{
if
(
PyDict_Check
(
op
))
if
(
PyDict_Check
(
op
))
{
return
handle
(
op
).
inc_ref
().
ptr
();
}
return
PyObject_CallFunctionObjArgs
((
PyObject
*
)
&
PyDict_Type
,
op
,
nullptr
);
}
};
...
...
@@ -1558,8 +1610,9 @@ public:
PYBIND11_OBJECT_DEFAULT
(
sequence
,
object
,
PySequence_Check
)
size_t
size
()
const
{
ssize_t
result
=
PySequence_Size
(
m_ptr
);
if
(
result
==
-
1
)
if
(
result
==
-
1
)
{
throw
error_already_set
();
}
return
(
size_t
)
result
;
}
bool
empty
()
const
{
return
size
()
==
0
;
}
...
...
@@ -1576,7 +1629,9 @@ public:
detail
::
enable_if_t
<
std
::
is_integral
<
SzType
>
::
value
,
int
>
=
0
>
// Some compilers generate link errors when using `const SzType &` here:
explicit
list
(
SzType
size
=
0
)
:
object
(
PyList_New
(
ssize_t_cast
(
size
)),
stolen_t
{})
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate list object!"
);
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate list object!"
);
}
}
size_t
size
()
const
{
return
(
size_t
)
PyList_Size
(
m_ptr
);
}
bool
empty
()
const
{
return
size
()
==
0
;
}
...
...
@@ -1603,7 +1658,9 @@ class set : public object {
public:
PYBIND11_OBJECT_CVT
(
set
,
object
,
PySet_Check
,
PySet_New
)
set
()
:
object
(
PySet_New
(
nullptr
),
stolen_t
{})
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate set object!"
);
if
(
!
m_ptr
)
{
pybind11_fail
(
"Could not allocate set object!"
);
}
}
size_t
size
()
const
{
return
(
size_t
)
PySet_Size
(
m_ptr
);
}
bool
empty
()
const
{
return
size
()
==
0
;
}
...
...
@@ -1621,8 +1678,9 @@ public:
PYBIND11_OBJECT_DEFAULT
(
function
,
object
,
PyCallable_Check
)
handle
cpp_function
()
const
{
handle
fun
=
detail
::
get_function
(
m_ptr
);
if
(
fun
&&
PyCFunction_Check
(
fun
.
ptr
()))
if
(
fun
&&
PyCFunction_Check
(
fun
.
ptr
()))
{
return
fun
;
}
return
handle
();
}
bool
is_cpp_function
()
const
{
return
(
bool
)
cpp_function
();
}
...
...
@@ -1639,7 +1697,9 @@ public:
buffer_info
request
(
bool
writable
=
false
)
const
{
int
flags
=
PyBUF_STRIDES
|
PyBUF_FORMAT
;
if
(
writable
)
flags
|=
PyBUF_WRITABLE
;
if
(
writable
)
{
flags
|=
PyBUF_WRITABLE
;
}
auto
*
view
=
new
Py_buffer
();
if
(
PyObject_GetBuffer
(
m_ptr
,
view
,
flags
)
!=
0
)
{
delete
view
;
...
...
@@ -1663,14 +1723,16 @@ public:
use ``memoryview(const object& obj)`` instead of this constructor.
\endrst */
explicit
memoryview
(
const
buffer_info
&
info
)
{
if
(
!
info
.
view
())
if
(
!
info
.
view
())
{
pybind11_fail
(
"Prohibited to create memoryview without Py_buffer"
);
}
// Note: PyMemoryView_FromBuffer never increments obj reference.
m_ptr
=
(
info
.
view
()
->
obj
)
?
PyMemoryView_FromObject
(
info
.
view
()
->
obj
)
:
PyMemoryView_FromBuffer
(
info
.
view
());
if
(
!
m_ptr
)
if
(
!
m_ptr
)
{
pybind11_fail
(
"Unable to create memoryview from buffer descriptor"
);
}
}
/** \rst
...
...
@@ -1744,8 +1806,9 @@ public:
PyObject
*
ptr
=
PyMemoryView_FromMemory
(
reinterpret_cast
<
char
*>
(
mem
),
size
,
(
readonly
)
?
PyBUF_READ
:
PyBUF_WRITE
);
if
(
!
ptr
)
if
(
!
ptr
)
{
pybind11_fail
(
"Could not allocate memoryview object!"
);
}
return
memoryview
(
object
(
ptr
,
stolen_t
{}));
}
...
...
@@ -1768,11 +1831,13 @@ inline memoryview memoryview::from_buffer(
detail
::
any_container
<
ssize_t
>
shape
,
detail
::
any_container
<
ssize_t
>
strides
,
bool
readonly
)
{
size_t
ndim
=
shape
->
size
();
if
(
ndim
!=
strides
->
size
())
if
(
ndim
!=
strides
->
size
())
{
pybind11_fail
(
"memoryview: shape length doesn't match strides length"
);
}
ssize_t
size
=
ndim
!=
0u
?
1
:
0
;
for
(
size_t
i
=
0
;
i
<
ndim
;
++
i
)
for
(
size_t
i
=
0
;
i
<
ndim
;
++
i
)
{
size
*=
(
*
shape
)[
i
];
}
Py_buffer
view
;
view
.
buf
=
ptr
;
view
.
obj
=
nullptr
;
...
...
@@ -1786,8 +1851,9 @@ inline memoryview memoryview::from_buffer(
view
.
suboffsets
=
nullptr
;
view
.
internal
=
nullptr
;
PyObject
*
obj
=
PyMemoryView_FromBuffer
(
&
view
);
if
(
!
obj
)
if
(
!
obj
)
{
throw
error_already_set
();
}
return
memoryview
(
object
(
obj
,
stolen_t
{}));
}
/// @endcond
...
...
@@ -1799,8 +1865,9 @@ inline memoryview memoryview::from_buffer(
/// Get the length of a Python object.
inline
size_t
len
(
handle
h
)
{
ssize_t
result
=
PyObject_Length
(
h
.
ptr
());
if
(
result
<
0
)
if
(
result
<
0
)
{
throw
error_already_set
();
}
return
(
size_t
)
result
;
}
...
...
@@ -1823,7 +1890,9 @@ inline size_t len_hint(handle h) {
inline
str
repr
(
handle
h
)
{
PyObject
*
str_value
=
PyObject_Repr
(
h
.
ptr
());
if
(
!
str_value
)
throw
error_already_set
();
if
(
!
str_value
)
{
throw
error_already_set
();
}
#if PY_MAJOR_VERSION < 3
PyObject
*
unicode
=
PyUnicode_FromEncodedObject
(
str_value
,
"utf-8"
,
nullptr
);
Py_XDECREF
(
str_value
);
str_value
=
unicode
;
...
...
@@ -1873,8 +1942,9 @@ handle object_api<D>::get_type() const { return type::handle_of(derived()); }
template
<
typename
D
>
bool
object_api
<
D
>::
rich_compare
(
object_api
const
&
other
,
int
value
)
const
{
int
rv
=
PyObject_RichCompareBool
(
derived
().
ptr
(),
other
.
derived
().
ptr
(),
value
);
if
(
rv
==
-
1
)
if
(
rv
==
-
1
)
{
throw
error_already_set
();
}
return
rv
==
1
;
}
...
...
Prev
1
2
3
Next
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