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
0a014e91
Commit
0a014e91
authored
Sep 26, 2016
by
Wenzel Jakob
Committed by
GitHub
Sep 26, 2016
Browse files
Merge pull request #425 from dean0x7d/accessors
Make the accessor interface more complete
parents
2d9220f0
2bab5793
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
381 additions
and
174 deletions
+381
-174
docs/changelog.rst
docs/changelog.rst
+2
-0
include/pybind11/attr.h
include/pybind11/attr.h
+1
-1
include/pybind11/cast.h
include/pybind11/cast.h
+16
-11
include/pybind11/numpy.h
include/pybind11/numpy.h
+4
-6
include/pybind11/pybind11.h
include/pybind11/pybind11.h
+31
-28
include/pybind11/pytypes.h
include/pybind11/pytypes.h
+217
-124
tests/constructor_stats.h
tests/constructor_stats.h
+1
-1
tests/pybind11_tests.cpp
tests/pybind11_tests.cpp
+1
-1
tests/test_python_types.cpp
tests/test_python_types.cpp
+69
-2
tests/test_python_types.py
tests/test_python_types.py
+39
-0
No files found.
docs/changelog.rst
View file @
0a014e91
...
@@ -53,6 +53,8 @@ Breaking changes queued for v2.0.0 (Not yet released)
...
@@ -53,6 +53,8 @@ Breaking changes queued for v2.0.0 (Not yet released)
* Added ``py::dict`` keyword constructor:``auto d = dict("number"_a=42, "name"_a="World");``
* Added ``py::dict`` keyword constructor:``auto d = dict("number"_a=42, "name"_a="World");``
* Added ``py::str::format()`` method and ``_s`` literal:
* Added ``py::str::format()`` method and ``_s`` literal:
``py::str s = "1 + 2 = {}"_s.format(3);``
``py::str s = "1 + 2 = {}"_s.format(3);``
* Attribute and item accessors now have a more complete interface which makes it possible
to chain attributes ``obj.attr("a")[key].attr("b").attr("method")(1, 2, 3)```.
* Various minor improvements of library internals (no user-visible changes)
* Various minor improvements of library internals (no user-visible changes)
1.8.1 (July 12, 2016)
1.8.1 (July 12, 2016)
...
...
include/pybind11/attr.h
View file @
0a014e91
...
@@ -276,7 +276,7 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
...
@@ -276,7 +276,7 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
/// Process a parent class attribute
/// Process a parent class attribute
template
<
typename
T
>
template
<
typename
T
>
struct
process_attribute
<
T
,
enable_if_t
<
std
::
is_base_of
<
handle
,
T
>::
value
>>
:
process_attribute_default
<
handle
>
{
struct
process_attribute
<
T
,
enable_if_t
<
is_pyobject
<
T
>::
value
>>
:
process_attribute_default
<
handle
>
{
static
void
init
(
const
handle
&
h
,
type_record
*
r
)
{
r
->
bases
.
append
(
h
);
}
static
void
init
(
const
handle
&
h
,
type_record
*
r
)
{
r
->
bases
.
append
(
h
);
}
};
};
...
...
include/pybind11/cast.h
View file @
0a014e91
...
@@ -39,7 +39,10 @@ PYBIND11_NOINLINE inline internals &get_internals() {
...
@@ -39,7 +39,10 @@ PYBIND11_NOINLINE inline internals &get_internals() {
return
*
internals_ptr
;
return
*
internals_ptr
;
handle
builtins
(
PyEval_GetBuiltins
());
handle
builtins
(
PyEval_GetBuiltins
());
const
char
*
id
=
PYBIND11_INTERNALS_ID
;
const
char
*
id
=
PYBIND11_INTERNALS_ID
;
capsule
caps
(
builtins
[
id
]);
capsule
caps
;
if
(
builtins
.
contains
(
id
))
{
caps
=
builtins
[
id
];
}
if
(
caps
.
check
())
{
if
(
caps
.
check
())
{
internals_ptr
=
caps
;
internals_ptr
=
caps
;
}
else
{
}
else
{
...
@@ -908,7 +911,7 @@ template <> struct handle_type_name<args> { static PYBIND11_DESCR name() { retur
...
@@ -908,7 +911,7 @@ template <> struct handle_type_name<args> { static PYBIND11_DESCR name() { retur
template
<
>
struct
handle_type_name
<
kwargs
>
{
static
PYBIND11_DESCR
name
()
{
return
_
(
"**kwargs"
);
}
};
template
<
>
struct
handle_type_name
<
kwargs
>
{
static
PYBIND11_DESCR
name
()
{
return
_
(
"**kwargs"
);
}
};
template
<
typename
type
>
template
<
typename
type
>
struct
type_caster
<
type
,
enable_if_t
<
std
::
is_base_of
<
handle
,
type
>::
value
>>
{
struct
type_caster
<
type
,
enable_if_t
<
is_pyobject
<
type
>::
value
>>
{
public:
public:
template
<
typename
T
=
type
,
enable_if_t
<!
std
::
is_base_of
<
object
,
T
>
::
value
,
int
>
=
0
>
template
<
typename
T
=
type
,
enable_if_t
<!
std
::
is_base_of
<
object
,
T
>
::
value
,
int
>
=
0
>
bool
load
(
handle
src
,
bool
/* convert */
)
{
value
=
type
(
src
);
return
value
.
check
();
}
bool
load
(
handle
src
,
bool
/* convert */
)
{
value
=
type
(
src
);
return
value
.
check
();
}
...
@@ -1216,12 +1219,12 @@ private:
...
@@ -1216,12 +1219,12 @@ private:
void
process
(
list
&
args_list
,
detail
::
args_proxy
ap
)
{
void
process
(
list
&
args_list
,
detail
::
args_proxy
ap
)
{
for
(
const
auto
&
a
:
ap
)
{
for
(
const
auto
&
a
:
ap
)
{
args_list
.
append
(
a
.
cast
<
object
>
()
);
args_list
.
append
(
a
);
}
}
}
}
void
process
(
list
&
/*args_list*/
,
arg_v
a
)
{
void
process
(
list
&
/*args_list*/
,
arg_v
a
)
{
if
(
m_kwargs
[
a
.
name
]
)
{
if
(
m_kwargs
.
contains
(
a
.
name
)
)
{
#if defined(NDEBUG)
#if defined(NDEBUG)
multiple_values_error
();
multiple_values_error
();
#else
#else
...
@@ -1240,7 +1243,7 @@ private:
...
@@ -1240,7 +1243,7 @@ private:
void
process
(
list
&
/*args_list*/
,
detail
::
kwargs_proxy
kp
)
{
void
process
(
list
&
/*args_list*/
,
detail
::
kwargs_proxy
kp
)
{
for
(
const
auto
&
k
:
dict
(
kp
,
true
))
{
for
(
const
auto
&
k
:
dict
(
kp
,
true
))
{
if
(
m_kwargs
[
k
.
first
]
)
{
if
(
m_kwargs
.
contains
(
k
.
first
)
)
{
#if defined(NDEBUG)
#if defined(NDEBUG)
multiple_values_error
();
multiple_values_error
();
#else
#else
...
@@ -1296,18 +1299,20 @@ unpacking_collector<policy> collect_arguments(Args &&...args) {
...
@@ -1296,18 +1299,20 @@ unpacking_collector<policy> collect_arguments(Args &&...args) {
return
{
std
::
forward
<
Args
>
(
args
)...
};
return
{
std
::
forward
<
Args
>
(
args
)...
};
}
}
NAMESPACE_END
(
detail
)
template
<
typename
Derived
>
template
<
return_value_policy
policy
,
typename
...
Args
>
template
<
return_value_policy
policy
,
typename
...
Args
>
object
handle
::
operator
()(
Args
&&
...
args
)
const
{
object
object_api
<
Derived
>
::
operator
()(
Args
&&
...
args
)
const
{
return
detail
::
collect_arguments
<
policy
>
(
std
::
forward
<
Args
>
(
args
)...).
call
(
m_
ptr
);
return
detail
::
collect_arguments
<
policy
>
(
std
::
forward
<
Args
>
(
args
)...).
call
(
derived
().
ptr
()
);
}
}
template
<
return_value_policy
policy
,
template
<
typename
Derived
>
typename
...
Args
>
object
handle
::
call
(
Args
&&
...
args
)
const
{
template
<
return_value_policy
policy
,
typename
...
Args
>
object
object_api
<
Derived
>::
call
(
Args
&&
...
args
)
const
{
return
operator
()
<
policy
>
(
std
::
forward
<
Args
>
(
args
)...);
return
operator
()
<
policy
>
(
std
::
forward
<
Args
>
(
args
)...);
}
}
NAMESPACE_END
(
detail
)
#define PYBIND11_MAKE_OPAQUE(Type) \
#define PYBIND11_MAKE_OPAQUE(Type) \
namespace pybind11 { namespace detail { \
namespace pybind11 { namespace detail { \
template<> class type_caster<Type> : public type_caster_base<Type> { }; \
template<> class type_caster<Type> : public type_caster_base<Type> { }; \
...
...
include/pybind11/numpy.h
View file @
0a014e91
...
@@ -125,11 +125,11 @@ private:
...
@@ -125,11 +125,11 @@ private:
static
npy_api
lookup
()
{
static
npy_api
lookup
()
{
module
m
=
module
::
import
(
"numpy.core.multiarray"
);
module
m
=
module
::
import
(
"numpy.core.multiarray"
);
object
c
=
(
object
)
m
.
attr
(
"_ARRAY_API"
);
auto
c
=
m
.
attr
(
"_ARRAY_API"
);
#if PY_MAJOR_VERSION >= 3
#if PY_MAJOR_VERSION >= 3
void
**
api_ptr
=
(
void
**
)
(
c
?
PyCapsule_GetPointer
(
c
.
ptr
(),
NULL
)
:
nullptr
)
;
void
**
api_ptr
=
(
void
**
)
PyCapsule_GetPointer
(
c
.
ptr
(),
NULL
);
#else
#else
void
**
api_ptr
=
(
void
**
)
(
c
?
PyCObject_AsVoidPtr
(
c
.
ptr
())
:
nullptr
)
;
void
**
api_ptr
=
(
void
**
)
PyCObject_AsVoidPtr
(
c
.
ptr
());
#endif
#endif
npy_api
api
;
npy_api
api
;
#define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func];
#define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func];
...
@@ -220,9 +220,7 @@ private:
...
@@ -220,9 +220,7 @@ private:
struct
field_descr
{
PYBIND11_STR_TYPE
name
;
object
format
;
pybind11
::
int_
offset
;
};
struct
field_descr
{
PYBIND11_STR_TYPE
name
;
object
format
;
pybind11
::
int_
offset
;
};
std
::
vector
<
field_descr
>
field_descriptors
;
std
::
vector
<
field_descr
>
field_descriptors
;
auto
fields
=
attr
(
"fields"
).
cast
<
object
>
();
for
(
auto
field
:
attr
(
"fields"
).
attr
(
"items"
)())
{
auto
items
=
fields
.
attr
(
"items"
).
cast
<
object
>
();
for
(
auto
field
:
items
())
{
auto
spec
=
object
(
field
,
true
).
cast
<
tuple
>
();
auto
spec
=
object
(
field
,
true
).
cast
<
tuple
>
();
auto
name
=
spec
[
0
].
cast
<
pybind11
::
str
>
();
auto
name
=
spec
[
0
].
cast
<
pybind11
::
str
>
();
auto
format
=
spec
[
1
].
cast
<
tuple
>
()[
0
].
cast
<
dtype
>
();
auto
format
=
spec
[
1
].
cast
<
tuple
>
()[
0
].
cast
<
dtype
>
();
...
...
include/pybind11/pybind11.h
View file @
0a014e91
...
@@ -18,6 +18,7 @@
...
@@ -18,6 +18,7 @@
# pragma warning(disable: 4800) // warning C4800: 'int': forcing value to bool 'true' or 'false' (performance warning)
# pragma warning(disable: 4800) // warning C4800: 'int': forcing value to bool 'true' or 'false' (performance warning)
# pragma warning(disable: 4996) // warning C4996: The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name
# pragma warning(disable: 4996) // warning C4996: The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name
# pragma warning(disable: 4702) // warning C4702: unreachable code
# pragma warning(disable: 4702) // warning C4702: unreachable code
# pragma warning(disable: 4522) // warning C4522: multiple assignment operators specified
#elif defined(__INTEL_COMPILER)
#elif defined(__INTEL_COMPILER)
# pragma warning(push)
# pragma warning(push)
# pragma warning(disable: 186) // pointless comparison of unsigned integer with zero
# pragma warning(disable: 186) // pointless comparison of unsigned integer with zero
...
@@ -176,7 +177,7 @@ protected:
...
@@ -176,7 +177,7 @@ protected:
if
(
a
.
descr
)
if
(
a
.
descr
)
a
.
descr
=
strdup
(
a
.
descr
);
a
.
descr
=
strdup
(
a
.
descr
);
else
if
(
a
.
value
)
else
if
(
a
.
value
)
a
.
descr
=
strdup
(
((
std
::
string
)
((
object
)
handle
(
a
.
value
)
.
attr
(
"__repr__"
)
)
().
str
()
).
c_str
());
a
.
descr
=
strdup
(
a
.
value
.
attr
(
"__repr__"
)().
cast
<
std
::
string
>
(
).
c_str
());
}
}
auto
const
&
registered_types
=
detail
::
get_internals
().
registered_types_cpp
;
auto
const
&
registered_types
=
detail
::
get_internals
().
registered_types_cpp
;
...
@@ -278,9 +279,11 @@ protected:
...
@@ -278,9 +279,11 @@ protected:
object
scope_module
;
object
scope_module
;
if
(
rec
->
scope
)
{
if
(
rec
->
scope
)
{
scope_module
=
(
object
)
rec
->
scope
.
attr
(
"__module__"
);
if
(
hasattr
(
rec
->
scope
,
"__module__"
))
{
if
(
!
scope_module
)
scope_module
=
rec
->
scope
.
attr
(
"__module__"
);
scope_module
=
(
object
)
rec
->
scope
.
attr
(
"__name__"
);
}
else
if
(
hasattr
(
rec
->
scope
,
"__name__"
))
{
scope_module
=
rec
->
scope
.
attr
(
"__name__"
);
}
}
}
m_ptr
=
PyCFunction_NewEx
(
rec
->
def
,
rec_capsule
.
ptr
(),
scope_module
.
ptr
());
m_ptr
=
PyCFunction_NewEx
(
rec
->
def
,
rec_capsule
.
ptr
(),
scope_module
.
ptr
());
...
@@ -544,8 +547,8 @@ public:
...
@@ -544,8 +547,8 @@ public:
template
<
typename
Func
,
typename
...
Extra
>
template
<
typename
Func
,
typename
...
Extra
>
module
&
def
(
const
char
*
name_
,
Func
&&
f
,
const
Extra
&
...
extra
)
{
module
&
def
(
const
char
*
name_
,
Func
&&
f
,
const
Extra
&
...
extra
)
{
cpp_function
func
(
std
::
forward
<
Func
>
(
f
),
name
(
name_
),
cpp_function
func
(
std
::
forward
<
Func
>
(
f
),
name
(
name_
),
scope
(
*
this
),
sibling
(
(
handle
)
attr
(
name_
)),
scope
(
*
this
),
extra
...);
sibling
(
getattr
(
*
this
,
name_
,
none
())
),
extra
...);
/* PyModule_AddObject steals a reference to 'func' */
/* PyModule_AddObject steals a reference to 'func' */
PyModule_AddObject
(
ptr
(),
name_
,
func
.
inc_ref
().
ptr
());
PyModule_AddObject
(
ptr
(),
name_
,
func
.
inc_ref
().
ptr
());
return
*
this
;
return
*
this
;
...
@@ -588,16 +591,18 @@ protected:
...
@@ -588,16 +591,18 @@ protected:
object
name
(
PYBIND11_FROM_STRING
(
rec
->
name
),
false
);
object
name
(
PYBIND11_FROM_STRING
(
rec
->
name
),
false
);
object
scope_module
;
object
scope_module
;
if
(
rec
->
scope
)
{
if
(
rec
->
scope
)
{
scope_module
=
(
object
)
rec
->
scope
.
attr
(
"__module__"
);
if
(
hasattr
(
rec
->
scope
,
"__module__"
))
{
if
(
!
scope_module
)
scope_module
=
rec
->
scope
.
attr
(
"__module__"
);
scope_module
=
(
object
)
rec
->
scope
.
attr
(
"__name__"
);
}
else
if
(
hasattr
(
rec
->
scope
,
"__name__"
))
{
scope_module
=
rec
->
scope
.
attr
(
"__name__"
);
}
}
}
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
/* Qualified names for Python >= 3.3 */
/* Qualified names for Python >= 3.3 */
object
scope_qualname
;
object
scope_qualname
;
if
(
rec
->
scope
)
if
(
rec
->
scope
&&
hasattr
(
rec
->
scope
,
"__qualname__"
)
)
scope_qualname
=
(
object
)
rec
->
scope
.
attr
(
"__qualname__"
);
scope_qualname
=
rec
->
scope
.
attr
(
"__qualname__"
);
object
ht_qualname
;
object
ht_qualname
;
if
(
scope_qualname
)
{
if
(
scope_qualname
)
{
ht_qualname
=
object
(
PyUnicode_FromFormat
(
ht_qualname
=
object
(
PyUnicode_FromFormat
(
...
@@ -719,8 +724,7 @@ protected:
...
@@ -719,8 +724,7 @@ protected:
if
(
ob_type
==
&
PyType_Type
)
{
if
(
ob_type
==
&
PyType_Type
)
{
std
::
string
name_
=
std
::
string
(
ht_type
.
tp_name
)
+
"__Meta"
;
std
::
string
name_
=
std
::
string
(
ht_type
.
tp_name
)
+
"__Meta"
;
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
object
ht_qualname
(
PyUnicode_FromFormat
(
object
ht_qualname
(
PyUnicode_FromFormat
(
"%U__Meta"
,
attr
(
"__qualname__"
).
ptr
()),
false
);
"%U__Meta"
,
((
object
)
attr
(
"__qualname__"
)).
ptr
()),
false
);
#endif
#endif
object
name
(
PYBIND11_FROM_STRING
(
name_
.
c_str
()),
false
);
object
name
(
PYBIND11_FROM_STRING
(
name_
.
c_str
()),
false
);
object
type_holder
(
PyType_Type
.
tp_alloc
(
&
PyType_Type
,
0
),
false
);
object
type_holder
(
PyType_Type
.
tp_alloc
(
&
PyType_Type
,
0
),
false
);
...
@@ -894,17 +898,16 @@ public:
...
@@ -894,17 +898,16 @@ public:
template
<
typename
Func
,
typename
...
Extra
>
template
<
typename
Func
,
typename
...
Extra
>
class_
&
def
(
const
char
*
name_
,
Func
&&
f
,
const
Extra
&
...
extra
)
{
class_
&
def
(
const
char
*
name_
,
Func
&&
f
,
const
Extra
&
...
extra
)
{
cpp_function
cf
(
std
::
forward
<
Func
>
(
f
),
name
(
name_
),
cpp_function
cf
(
std
::
forward
<
Func
>
(
f
),
name
(
name_
),
is_method
(
*
this
),
sibling
(
attr
(
name_
)),
is_method
(
*
this
),
sibling
(
getattr
(
*
this
,
name_
,
none
())),
extra
...);
extra
...);
attr
(
cf
.
name
())
=
cf
;
attr
(
cf
.
name
())
=
cf
;
return
*
this
;
return
*
this
;
}
}
template
<
typename
Func
,
typename
...
Extra
>
class_
&
template
<
typename
Func
,
typename
...
Extra
>
class_
&
def_static
(
const
char
*
name_
,
Func
f
,
const
Extra
&
...
extra
)
{
def_static
(
const
char
*
name_
,
Func
f
,
const
Extra
&
...
extra
)
{
cpp_function
cf
(
std
::
forward
<
Func
>
(
f
),
name
(
name_
),
cpp_function
cf
(
std
::
forward
<
Func
>
(
f
),
name
(
name_
),
scope
(
*
this
),
sibling
(
attr
(
name_
)),
scope
(
*
this
),
extra
...);
sibling
(
get
attr
(
*
this
,
name_
,
none
())
),
extra
...);
attr
(
cf
.
name
())
=
cf
;
attr
(
cf
.
name
())
=
cf
;
return
*
this
;
return
*
this
;
}
}
...
@@ -1336,19 +1339,19 @@ NAMESPACE_BEGIN(detail)
...
@@ -1336,19 +1339,19 @@ NAMESPACE_BEGIN(detail)
PYBIND11_NOINLINE
inline
void
print
(
tuple
args
,
dict
kwargs
)
{
PYBIND11_NOINLINE
inline
void
print
(
tuple
args
,
dict
kwargs
)
{
auto
strings
=
tuple
(
args
.
size
());
auto
strings
=
tuple
(
args
.
size
());
for
(
size_t
i
=
0
;
i
<
args
.
size
();
++
i
)
{
for
(
size_t
i
=
0
;
i
<
args
.
size
();
++
i
)
{
strings
[
i
]
=
args
[
i
].
cast
<
object
>
().
str
();
strings
[
i
]
=
args
[
i
].
str
();
}
}
auto
sep
=
kwargs
[
"sep"
]
?
kwargs
[
"sep"
]
:
cast
(
" "
);
auto
sep
=
kwargs
.
contains
(
"sep"
)
?
kwargs
[
"sep"
]
:
cast
(
" "
);
auto
line
=
sep
.
attr
(
"join"
)
.
cast
<
object
>
()
(
strings
);
auto
line
=
sep
.
attr
(
"join"
)(
strings
);
auto
file
=
kwargs
[
"file"
]
?
kwargs
[
"file"
].
cast
<
object
>
()
auto
file
=
kwargs
.
contains
(
"file"
)
?
kwargs
[
"file"
].
cast
<
object
>
()
:
module
::
import
(
"sys"
).
attr
(
"stdout"
);
:
module
::
import
(
"sys"
).
attr
(
"stdout"
);
auto
write
=
file
.
attr
(
"write"
)
.
cast
<
object
>
()
;
auto
write
=
file
.
attr
(
"write"
);
write
(
line
);
write
(
line
);
write
(
kwargs
[
"end"
]
?
kwargs
[
"end"
]
:
cast
(
"
\n
"
));
write
(
kwargs
.
contains
(
"end"
)
?
kwargs
[
"end"
]
:
cast
(
"
\n
"
));
if
(
kwargs
[
"flush"
]
&&
kwargs
[
"flush"
].
cast
<
bool
>
())
{
if
(
kwargs
.
contains
(
"flush"
)
&&
kwargs
[
"flush"
].
cast
<
bool
>
())
{
file
.
attr
(
"flush"
)
.
cast
<
object
>
()
();
file
.
attr
(
"flush"
)();
}
}
}
}
NAMESPACE_END
(
detail
)
NAMESPACE_END
(
detail
)
...
@@ -1500,7 +1503,7 @@ inline function get_type_overload(const void *this_ptr, const detail::type_info
...
@@ -1500,7 +1503,7 @@ inline function get_type_overload(const void *this_ptr, const detail::type_info
if
(
cache
.
find
(
key
)
!=
cache
.
end
())
if
(
cache
.
find
(
key
)
!=
cache
.
end
())
return
function
();
return
function
();
function
overload
=
(
function
)
py_object
.
attr
(
name
);
function
overload
=
getattr
(
py_object
,
name
,
function
()
);
if
(
overload
.
is_cpp_function
())
{
if
(
overload
.
is_cpp_function
())
{
cache
.
insert
(
key
);
cache
.
insert
(
key
);
return
function
();
return
function
();
...
...
include/pybind11/pytypes.h
View file @
0a014e91
...
@@ -16,50 +16,88 @@
...
@@ -16,50 +16,88 @@
NAMESPACE_BEGIN
(
pybind11
)
NAMESPACE_BEGIN
(
pybind11
)
/* A few forward declarations */
/* A few forward declarations */
class
object
;
class
str
;
class
iterator
;
class
handle
;
class
object
;
class
str
;
class
iterator
;
struct
arg
;
struct
arg_v
;
struct
arg
;
struct
arg_v
;
namespace
detail
{
class
accessor
;
class
args_proxy
;
class
kwargs_proxy
;
}
NAMESPACE_BEGIN
(
detail
)
class
args_proxy
;
// Accessor forward declarations
template
<
typename
Policy
>
class
accessor
;
namespace
accessor_policies
{
struct
obj_attr
;
struct
str_attr
;
struct
generic_item
;
struct
list_item
;
struct
tuple_item
;
}
using
obj_attr_accessor
=
accessor
<
accessor_policies
::
obj_attr
>
;
using
str_attr_accessor
=
accessor
<
accessor_policies
::
str_attr
>
;
using
item_accessor
=
accessor
<
accessor_policies
::
generic_item
>
;
using
list_accessor
=
accessor
<
accessor_policies
::
list_item
>
;
using
tuple_accessor
=
accessor
<
accessor_policies
::
tuple_item
>
;
/// Tag and check to identify a class which implements the Python object API
class
pyobject_tag
{
};
template
<
typename
T
>
using
is_pyobject
=
std
::
is_base_of
<
pyobject_tag
,
T
>
;
/// Mixin which adds common functions to handle, object and various accessors.
/// The only requirement for `Derived` is to implement `PyObject *Derived::ptr() const`.
template
<
typename
Derived
>
class
object_api
:
public
pyobject_tag
{
const
Derived
&
derived
()
const
{
return
static_cast
<
const
Derived
&>
(
*
this
);
}
public:
iterator
begin
()
const
;
iterator
end
()
const
;
item_accessor
operator
[](
handle
key
)
const
;
item_accessor
operator
[](
const
char
*
key
)
const
;
obj_attr_accessor
attr
(
handle
key
)
const
;
str_attr_accessor
attr
(
const
char
*
key
)
const
;
args_proxy
operator
*
()
const
;
template
<
typename
T
>
bool
contains
(
T
&&
key
)
const
;
template
<
return_value_policy
policy
=
return_value_policy
::
automatic_reference
,
typename
...
Args
>
object
operator
()(
Args
&&
...
args
)
const
;
template
<
return_value_policy
policy
=
return_value_policy
::
automatic_reference
,
typename
...
Args
>
PYBIND11_DEPRECATED
(
"call(...) was deprecated in favor of operator()(...)"
)
object
call
(
Args
&&
...
args
)
const
;
bool
is_none
()
const
{
return
derived
().
ptr
()
==
Py_None
;
}
pybind11
::
str
str
()
const
;
pybind11
::
str
repr
()
const
;
int
ref_count
()
const
{
return
static_cast
<
int
>
(
Py_REFCNT
(
derived
().
ptr
()));
}
handle
get_type
()
const
;
};
NAMESPACE_END
(
detail
)
/// Holds a reference to a Python object (no reference counting)
/// Holds a reference to a Python object (no reference counting)
class
handle
{
class
handle
:
public
detail
::
object_api
<
handle
>
{
public:
public:
handle
()
:
m_ptr
(
nullptr
)
{
}
handle
()
=
default
;
handle
(
const
handle
&
other
)
:
m_ptr
(
other
.
m_ptr
)
{
}
handle
(
PyObject
*
ptr
)
:
m_ptr
(
ptr
)
{
}
handle
(
PyObject
*
ptr
)
:
m_ptr
(
ptr
)
{
}
PyObject
*
ptr
()
const
{
return
m_ptr
;
}
PyObject
*
ptr
()
const
{
return
m_ptr
;
}
PyObject
*&
ptr
()
{
return
m_ptr
;
}
PyObject
*&
ptr
()
{
return
m_ptr
;
}
const
handle
&
inc_ref
()
const
{
Py_XINCREF
(
m_ptr
);
return
*
this
;
}
const
handle
&
inc_ref
()
const
{
Py_XINCREF
(
m_ptr
);
return
*
this
;
}
const
handle
&
dec_ref
()
const
{
Py_XDECREF
(
m_ptr
);
return
*
this
;
}
const
handle
&
dec_ref
()
const
{
Py_XDECREF
(
m_ptr
);
return
*
this
;
}
int
ref_count
()
const
{
return
(
int
)
Py_REFCNT
(
m_ptr
);
}
handle
get_type
()
const
{
return
handle
((
PyObject
*
)
Py_TYPE
(
m_ptr
));
}
inline
iterator
begin
()
const
;
inline
iterator
end
()
const
;
inline
detail
::
accessor
operator
[](
handle
key
)
const
;
inline
detail
::
accessor
operator
[](
const
char
*
key
)
const
;
inline
detail
::
accessor
attr
(
handle
key
)
const
;
inline
detail
::
accessor
attr
(
const
char
*
key
)
const
;
inline
pybind11
::
str
str
()
const
;
inline
pybind11
::
str
repr
()
const
;
bool
is_none
()
const
{
return
m_ptr
==
Py_None
;
}
template
<
typename
T
>
T
cast
()
const
;
template
<
typename
T
>
T
cast
()
const
;
template
<
return_value_policy
policy
=
return_value_policy
::
automatic_reference
,
typename
...
Args
>
PYBIND11_DEPRECATED
(
"call(...) was deprecated in favor of operator()(...)"
)
object
call
(
Args
&&
...
args
)
const
;
template
<
return_value_policy
policy
=
return_value_policy
::
automatic_reference
,
typename
...
Args
>
object
operator
()(
Args
&&
...
args
)
const
;
operator
bool
()
const
{
return
m_ptr
!=
nullptr
;
}
operator
bool
()
const
{
return
m_ptr
!=
nullptr
;
}
bool
operator
==
(
const
handle
&
h
)
const
{
return
m_ptr
==
h
.
m_ptr
;
}
bool
operator
==
(
const
handle
&
h
)
const
{
return
m_ptr
==
h
.
m_ptr
;
}
bool
operator
!=
(
const
handle
&
h
)
const
{
return
m_ptr
!=
h
.
m_ptr
;
}
bool
operator
!=
(
const
handle
&
h
)
const
{
return
m_ptr
!=
h
.
m_ptr
;
}
bool
check
()
const
{
return
m_ptr
!=
nullptr
;
}
bool
check
()
const
{
return
m_ptr
!=
nullptr
;
}
inline
detail
::
args_proxy
operator
*
()
const
;
protected:
protected:
PyObject
*
m_ptr
;
PyObject
*
m_ptr
=
nullptr
;
};
};
/// Holds a reference to a Python object (with reference counting)
/// Holds a reference to a Python object (with reference counting)
class
object
:
public
handle
{
class
object
:
public
handle
{
public:
public:
object
()
{
}
object
()
=
default
;
object
(
const
object
&
o
)
:
handle
(
o
)
{
inc_ref
();
}
object
(
const
object
&
o
)
:
handle
(
o
)
{
inc_ref
();
}
object
(
const
handle
&
h
,
bool
borrowed
)
:
handle
(
h
)
{
if
(
borrowed
)
inc_ref
();
}
object
(
const
handle
&
h
,
bool
borrowed
)
:
handle
(
h
)
{
if
(
borrowed
)
inc_ref
();
}
object
(
PyObject
*
ptr
,
bool
borrowed
)
:
handle
(
ptr
)
{
if
(
borrowed
)
inc_ref
();
}
object
(
PyObject
*
ptr
,
bool
borrowed
)
:
handle
(
ptr
)
{
if
(
borrowed
)
inc_ref
();
}
...
@@ -95,6 +133,52 @@ public:
...
@@ -95,6 +133,52 @@ public:
template
<
typename
T
>
T
cast
()
&&
;
template
<
typename
T
>
T
cast
()
&&
;
};
};
inline
bool
hasattr
(
handle
obj
,
handle
name
)
{
return
PyObject_HasAttr
(
obj
.
ptr
(),
name
.
ptr
())
==
1
;
}
inline
bool
hasattr
(
handle
obj
,
const
char
*
name
)
{
return
PyObject_HasAttrString
(
obj
.
ptr
(),
name
)
==
1
;
}
inline
object
getattr
(
handle
obj
,
handle
name
)
{
PyObject
*
result
=
PyObject_GetAttr
(
obj
.
ptr
(),
name
.
ptr
());
if
(
!
result
)
{
throw
error_already_set
();
}
return
{
result
,
false
};
}
inline
object
getattr
(
handle
obj
,
const
char
*
name
)
{
PyObject
*
result
=
PyObject_GetAttrString
(
obj
.
ptr
(),
name
);
if
(
!
result
)
{
throw
error_already_set
();
}
return
{
result
,
false
};
}
inline
object
getattr
(
handle
obj
,
handle
name
,
handle
default_
)
{
if
(
PyObject
*
result
=
PyObject_GetAttr
(
obj
.
ptr
(),
name
.
ptr
()))
{
return
{
result
,
false
};
}
else
{
PyErr_Clear
();
return
{
default_
,
true
};
}
}
inline
object
getattr
(
handle
obj
,
const
char
*
name
,
handle
default_
)
{
if
(
PyObject
*
result
=
PyObject_GetAttrString
(
obj
.
ptr
(),
name
))
{
return
{
result
,
false
};
}
else
{
PyErr_Clear
();
return
{
default_
,
true
};
}
}
inline
void
setattr
(
handle
obj
,
handle
name
,
handle
value
)
{
if
(
PyObject_SetAttr
(
obj
.
ptr
(),
name
.
ptr
(),
value
.
ptr
())
!=
0
)
{
throw
error_already_set
();
}
}
inline
void
setattr
(
handle
obj
,
const
char
*
name
,
handle
value
)
{
if
(
PyObject_SetAttrString
(
obj
.
ptr
(),
name
,
value
.
ptr
())
!=
0
)
{
throw
error_already_set
();
}
}
NAMESPACE_BEGIN
(
detail
)
NAMESPACE_BEGIN
(
detail
)
inline
handle
get_function
(
handle
value
)
{
inline
handle
get_function
(
handle
value
)
{
if
(
value
)
{
if
(
value
)
{
...
@@ -108,100 +192,97 @@ inline handle get_function(handle value) {
...
@@ -108,100 +192,97 @@ inline handle get_function(handle value) {
return
value
;
return
value
;
}
}
class
accessor
{
template
<
typename
Policy
>
class
accessor
:
public
object_api
<
accessor
<
Policy
>>
{
using
key_type
=
typename
Policy
::
key_type
;
public:
public:
accessor
(
handle
obj
,
handle
key
,
bool
attr
)
accessor
(
handle
obj
,
key_type
key
)
:
obj
(
obj
),
key
(
std
::
move
(
key
))
{
}
:
obj
(
obj
),
key
(
key
,
true
),
attr
(
attr
)
{
}
accessor
(
handle
obj
,
const
char
*
key
,
bool
attr
)
:
obj
(
obj
),
key
(
PyUnicode_FromString
(
key
),
false
),
attr
(
attr
)
{
}
accessor
(
const
accessor
&
a
)
:
obj
(
a
.
obj
),
key
(
a
.
key
),
attr
(
a
.
attr
)
{
}
void
operator
=
(
accessor
o
)
{
operator
=
(
object
(
o
));
}
void
operator
=
(
const
handle
&
value
)
{
if
(
attr
)
{
if
(
PyObject_SetAttr
(
obj
.
ptr
(),
key
.
ptr
(),
value
.
ptr
())
==
-
1
)
throw
error_already_set
();
}
else
{
if
(
PyObject_SetItem
(
obj
.
ptr
(),
key
.
ptr
(),
value
.
ptr
())
==
-
1
)
throw
error_already_set
();
}
}
operator
object
()
const
{
void
operator
=
(
const
accessor
&
a
)
&&
{
std
::
move
(
*
this
).
operator
=
(
handle
(
a
));
}
object
result
(
attr
?
PyObject_GetAttr
(
obj
.
ptr
(),
key
.
ptr
())
void
operator
=
(
const
accessor
&
a
)
&
{
operator
=
(
handle
(
a
));
}
:
PyObject_GetItem
(
obj
.
ptr
(),
key
.
ptr
()),
false
);
void
operator
=
(
const
object
&
o
)
&&
{
std
::
move
(
*
this
).
operator
=
(
handle
(
o
));
}
if
(
!
result
)
{
PyErr_Clear
(
);
}
void
operator
=
(
const
object
&
o
)
&
{
operator
=
(
handle
(
o
)
);
}
return
result
;
void
operator
=
(
handle
value
)
&&
{
Policy
::
set
(
obj
,
key
,
value
);
}
}
void
operator
=
(
handle
value
)
&
{
get_cache
()
=
object
(
value
,
true
);
}
template
<
typename
T
>
T
cast
()
const
{
return
operator
object
().
cast
<
T
>
();
}
operator
object
()
const
{
return
get_cache
();
}
PyObject
*
ptr
()
const
{
return
get_cache
().
ptr
();
}
template
<
typename
T
>
T
cast
()
const
{
return
get_cache
().
template
cast
<
T
>();
}
operator
bool
()
const
{
private:
if
(
attr
)
{
object
&
get_cache
()
const
{
return
(
bool
)
PyObject_HasAttr
(
obj
.
ptr
(),
key
.
ptr
());
if
(
!
cache
)
{
cache
=
Policy
::
get
(
obj
,
key
);
}
}
else
{
return
cache
;
object
result
(
PyObject_GetItem
(
obj
.
ptr
(),
key
.
ptr
()),
false
);
}
if
(
!
result
)
PyErr_Clear
();
return
(
bool
)
result
;
}
};
private:
private:
handle
obj
;
handle
obj
;
object
key
;
key_type
key
;
bool
attr
;
mutable
object
cache
;
};
};
struct
list_accessor
{
NAMESPACE_BEGIN
(
accessor_policies
)
public:
struct
obj_attr
{
list_accessor
(
handle
list
,
size_t
index
)
:
list
(
list
),
index
(
index
)
{
}
using
key_type
=
object
;
static
object
get
(
handle
obj
,
handle
key
)
{
return
getattr
(
obj
,
key
);
}
static
void
set
(
handle
obj
,
handle
key
,
handle
val
)
{
setattr
(
obj
,
key
,
val
);
}
};
void
operator
=
(
list_accessor
o
)
{
return
operator
=
(
object
(
o
));
}
struct
str_attr
{
using
key_type
=
const
char
*
;
static
object
get
(
handle
obj
,
const
char
*
key
)
{
return
getattr
(
obj
,
key
);
}
static
void
set
(
handle
obj
,
const
char
*
key
,
handle
val
)
{
setattr
(
obj
,
key
,
val
);
}
};
void
operator
=
(
const
handle
&
o
)
{
struct
generic_item
{
// PyList_SetItem steals a reference to 'o'
using
key_type
=
object
;
if
(
PyList_SetItem
(
list
.
ptr
(),
(
ssize_t
)
index
,
o
.
inc_ref
().
ptr
())
<
0
)
pybind11_fail
(
"Unable to assign value in Python list!"
);
}
operator
object
()
const
{
static
object
get
(
handle
obj
,
handle
key
)
{
PyObject
*
result
=
PyList_GetItem
(
list
.
ptr
(),
(
ssize_t
)
index
);
PyObject
*
result
=
PyObject_GetItem
(
obj
.
ptr
(),
key
.
ptr
());
if
(
!
result
)
if
(
!
result
)
{
throw
error_already_set
();
}
pybind11_fail
(
"Unable to retrieve value from Python list!"
);
return
{
result
,
false
};
return
object
(
result
,
true
);
}
}
template
<
typename
T
>
T
cast
()
const
{
return
operator
object
().
cast
<
T
>
();
}
static
void
set
(
handle
obj
,
handle
key
,
handle
val
)
{
private:
if
(
PyObject_SetItem
(
obj
.
ptr
(),
key
.
ptr
(),
val
.
ptr
())
!=
0
)
{
throw
error_already_set
();
}
handle
list
;
}
size_t
index
;
};
};
struct
tuple_accessor
{
struct
list_item
{
public:
using
key_type
=
size_t
;
tuple_accessor
(
handle
tuple
,
size_t
index
)
:
tuple
(
tuple
),
index
(
index
)
{
}
void
operator
=
(
tuple_accessor
o
)
{
return
operator
=
(
object
(
o
));
}
static
object
get
(
handle
obj
,
size_t
index
)
{
PyObject
*
result
=
PyList_GetItem
(
obj
.
ptr
(),
static_cast
<
ssize_t
>
(
index
));
if
(
!
result
)
{
throw
error_already_set
();
}
return
{
result
,
true
};
}
void
operator
=
(
const
handle
&
o
)
{
static
void
set
(
handle
obj
,
size_t
index
,
handle
val
)
{
// PyTuple_SetItem steals a referenceto 'o'
// PyList_SetItem steals a reference to 'val'
if
(
PyTuple_SetItem
(
tuple
.
ptr
(),
(
ssize_t
)
index
,
o
.
inc_ref
().
ptr
())
<
0
)
if
(
PyList_SetItem
(
obj
.
ptr
(),
static_cast
<
ssize_t
>
(
index
),
val
.
inc_ref
().
ptr
())
!=
0
)
{
pybind11_fail
(
"Unable to assign value in Python tuple!"
);
throw
error_already_set
();
}
}
}
};
struct
tuple_item
{
using
key_type
=
size_t
;
operator
object
()
const
{
static
object
get
(
handle
obj
,
size_t
index
)
{
PyObject
*
result
=
PyTuple_GetItem
(
tuple
.
ptr
(),
(
ssize_t
)
index
);
PyObject
*
result
=
PyTuple_GetItem
(
obj
.
ptr
(),
static_cast
<
ssize_t
>
(
index
));
if
(
!
result
)
if
(
!
result
)
{
throw
error_already_set
();
}
pybind11_fail
(
"Unable to retrieve value from Python tuple!"
);
return
{
result
,
true
};
return
object
(
result
,
true
);
}
}
template
<
typename
T
>
T
cast
()
const
{
return
operator
object
().
cast
<
T
>
();
}
static
void
set
(
handle
obj
,
size_t
index
,
handle
val
)
{
private:
// PyTuple_SetItem steals a reference to 'val'
handle
tuple
;
if
(
PyTuple_SetItem
(
obj
.
ptr
(),
static_cast
<
ssize_t
>
(
index
),
val
.
inc_ref
().
ptr
())
!=
0
)
{
size_t
index
;
throw
error_already_set
();
}
}
};
};
NAMESPACE_END
(
accessor_policies
)
struct
dict_iterator
{
struct
dict_iterator
{
public:
public:
...
@@ -347,14 +428,6 @@ public:
...
@@ -347,14 +428,6 @@ public:
PYBIND11_OBJECT_DEFAULT
(
iterable
,
object
,
detail
::
PyIterable_Check
)
PYBIND11_OBJECT_DEFAULT
(
iterable
,
object
,
detail
::
PyIterable_Check
)
};
};
inline
detail
::
accessor
handle
::
operator
[](
handle
key
)
const
{
return
detail
::
accessor
(
*
this
,
key
,
false
);
}
inline
detail
::
accessor
handle
::
operator
[](
const
char
*
key
)
const
{
return
detail
::
accessor
(
*
this
,
key
,
false
);
}
inline
detail
::
accessor
handle
::
attr
(
handle
key
)
const
{
return
detail
::
accessor
(
*
this
,
key
,
true
);
}
inline
detail
::
accessor
handle
::
attr
(
const
char
*
key
)
const
{
return
detail
::
accessor
(
*
this
,
key
,
true
);
}
inline
iterator
handle
::
begin
()
const
{
return
iterator
(
PyObject_GetIter
(
ptr
()),
false
);
}
inline
iterator
handle
::
end
()
const
{
return
iterator
(
nullptr
,
false
);
}
inline
detail
::
args_proxy
handle
::
operator
*
()
const
{
return
detail
::
args_proxy
(
*
this
);
}
class
bytes
;
class
bytes
;
class
str
:
public
object
{
class
str
:
public
object
{
...
@@ -391,7 +464,7 @@ public:
...
@@ -391,7 +464,7 @@ public:
template
<
typename
...
Args
>
template
<
typename
...
Args
>
str
format
(
Args
&&
...
args
)
const
{
str
format
(
Args
&&
...
args
)
const
{
return
attr
(
"format"
)
.
cast
<
object
>
()
(
std
::
forward
<
Args
>
(
args
)...);
return
attr
(
"format"
)(
std
::
forward
<
Args
>
(
args
)...);
}
}
};
};
...
@@ -400,24 +473,6 @@ inline namespace literals {
...
@@ -400,24 +473,6 @@ inline namespace literals {
inline
str
operator
""
_s
(
const
char
*
s
,
size_t
size
)
{
return
{
s
,
size
};
}
inline
str
operator
""
_s
(
const
char
*
s
,
size_t
size
)
{
return
{
s
,
size
};
}
}
}
inline
pybind11
::
str
handle
::
str
()
const
{
PyObject
*
strValue
=
PyObject_Str
(
m_ptr
);
#if PY_MAJOR_VERSION < 3
PyObject
*
unicode
=
PyUnicode_FromEncodedObject
(
strValue
,
"utf-8"
,
nullptr
);
Py_XDECREF
(
strValue
);
strValue
=
unicode
;
#endif
return
pybind11
::
str
(
strValue
,
false
);
}
inline
pybind11
::
str
handle
::
repr
()
const
{
PyObject
*
strValue
=
PyObject_Repr
(
m_ptr
);
#if PY_MAJOR_VERSION < 3
PyObject
*
unicode
=
PyUnicode_FromEncodedObject
(
strValue
,
"utf-8"
,
nullptr
);
Py_XDECREF
(
strValue
);
strValue
=
unicode
;
#endif
return
pybind11
::
str
(
strValue
,
false
);
}
class
bytes
:
public
object
{
class
bytes
:
public
object
{
public:
public:
PYBIND11_OBJECT_DEFAULT
(
bytes
,
object
,
PYBIND11_BYTES_CHECK
)
PYBIND11_OBJECT_DEFAULT
(
bytes
,
object
,
PYBIND11_BYTES_CHECK
)
...
@@ -583,7 +638,7 @@ public:
...
@@ -583,7 +638,7 @@ public:
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
);
}
size_t
size
()
const
{
return
(
size_t
)
PyTuple_Size
(
m_ptr
);
}
detail
::
tuple_accessor
operator
[](
size_t
index
)
const
{
return
detail
::
tuple_accessor
(
*
this
,
index
)
;
}
detail
::
tuple_accessor
operator
[](
size_t
index
)
const
{
return
{
*
this
,
index
}
;
}
};
};
class
dict
:
public
object
{
class
dict
:
public
object
{
...
@@ -602,6 +657,8 @@ public:
...
@@ -602,6 +657,8 @@ public:
detail
::
dict_iterator
begin
()
const
{
return
(
++
detail
::
dict_iterator
(
*
this
,
0
));
}
detail
::
dict_iterator
begin
()
const
{
return
(
++
detail
::
dict_iterator
(
*
this
,
0
));
}
detail
::
dict_iterator
end
()
const
{
return
detail
::
dict_iterator
();
}
detail
::
dict_iterator
end
()
const
{
return
detail
::
dict_iterator
();
}
void
clear
()
const
{
PyDict_Clear
(
ptr
());
}
void
clear
()
const
{
PyDict_Clear
(
ptr
());
}
bool
contains
(
handle
key
)
const
{
return
PyDict_Contains
(
ptr
(),
key
.
ptr
())
==
1
;
}
bool
contains
(
const
char
*
key
)
const
{
return
PyDict_Contains
(
ptr
(),
pybind11
::
str
(
key
).
ptr
())
==
1
;
}
};
};
class
list
:
public
object
{
class
list
:
public
object
{
...
@@ -611,7 +668,7 @@ public:
...
@@ -611,7 +668,7 @@ public:
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
);
}
size_t
size
()
const
{
return
(
size_t
)
PyList_Size
(
m_ptr
);
}
detail
::
list_accessor
operator
[](
size_t
index
)
const
{
return
detail
::
list_accessor
(
*
this
,
index
)
;
}
detail
::
list_accessor
operator
[](
size_t
index
)
const
{
return
{
*
this
,
index
}
;
}
void
append
(
handle
h
)
const
{
PyList_Append
(
m_ptr
,
h
.
ptr
());
}
void
append
(
handle
h
)
const
{
PyList_Append
(
m_ptr
,
h
.
ptr
());
}
};
};
...
@@ -691,4 +748,40 @@ inline size_t len(handle h) {
...
@@ -691,4 +748,40 @@ inline size_t len(handle h) {
return
(
size_t
)
result
;
return
(
size_t
)
result
;
}
}
NAMESPACE_BEGIN
(
detail
)
template
<
typename
D
>
iterator
object_api
<
D
>::
begin
()
const
{
return
{
PyObject_GetIter
(
derived
().
ptr
()),
false
};
}
template
<
typename
D
>
iterator
object_api
<
D
>::
end
()
const
{
return
{
nullptr
,
false
};
}
template
<
typename
D
>
item_accessor
object_api
<
D
>::
operator
[](
handle
key
)
const
{
return
{
derived
(),
object
(
key
,
true
)};
}
template
<
typename
D
>
item_accessor
object_api
<
D
>::
operator
[](
const
char
*
key
)
const
{
return
{
derived
(),
pybind11
::
str
(
key
)};
}
template
<
typename
D
>
obj_attr_accessor
object_api
<
D
>::
attr
(
handle
key
)
const
{
return
{
derived
(),
object
(
key
,
true
)};
}
template
<
typename
D
>
str_attr_accessor
object_api
<
D
>::
attr
(
const
char
*
key
)
const
{
return
{
derived
(),
key
};
}
template
<
typename
D
>
args_proxy
object_api
<
D
>::
operator
*
()
const
{
return
{
derived
().
ptr
()};
}
template
<
typename
D
>
template
<
typename
T
>
bool
object_api
<
D
>::
contains
(
T
&&
key
)
const
{
return
attr
(
"__contains__"
)(
std
::
forward
<
T
>
(
key
)).
template
cast
<
bool
>();
}
template
<
typename
D
>
pybind11
::
str
object_api
<
D
>::
str
()
const
{
PyObject
*
str_value
=
PyObject_Str
(
derived
().
ptr
());
#if PY_MAJOR_VERSION < 3
PyObject
*
unicode
=
PyUnicode_FromEncodedObject
(
str_value
,
"utf-8"
,
nullptr
);
Py_XDECREF
(
str_value
);
str_value
=
unicode
;
#endif
return
{
str_value
,
false
};
}
template
<
typename
D
>
pybind11
::
str
object_api
<
D
>::
repr
()
const
{
PyObject
*
str_value
=
PyObject_Repr
(
derived
().
ptr
());
#if PY_MAJOR_VERSION < 3
PyObject
*
unicode
=
PyUnicode_FromEncodedObject
(
str_value
,
"utf-8"
,
nullptr
);
Py_XDECREF
(
str_value
);
str_value
=
unicode
;
#endif
return
{
str_value
,
false
};
}
template
<
typename
D
>
handle
object_api
<
D
>::
get_type
()
const
{
return
(
PyObject
*
)
Py_TYPE
(
derived
().
ptr
());
}
NAMESPACE_END
(
detail
)
NAMESPACE_END
(
pybind11
)
NAMESPACE_END
(
pybind11
)
tests/constructor_stats.h
View file @
0a014e91
...
@@ -103,7 +103,7 @@ public:
...
@@ -103,7 +103,7 @@ public:
int
alive
()
{
int
alive
()
{
// Force garbage collection to ensure any pending destructors are invoked:
// Force garbage collection to ensure any pending destructors are invoked:
py
::
module
::
import
(
"gc"
).
attr
(
"collect"
)
.
operator
py
::
object
()
();
py
::
module
::
import
(
"gc"
).
attr
(
"collect"
)();
int
total
=
0
;
int
total
=
0
;
for
(
const
auto
&
p
:
_instances
)
if
(
p
.
second
>
0
)
total
+=
p
.
second
;
for
(
const
auto
&
p
:
_instances
)
if
(
p
.
second
>
0
)
total
+=
p
.
second
;
return
total
;
return
total
;
...
...
tests/pybind11_tests.cpp
View file @
0a014e91
...
@@ -39,7 +39,7 @@ PYBIND11_PLUGIN(pybind11_tests) {
...
@@ -39,7 +39,7 @@ PYBIND11_PLUGIN(pybind11_tests) {
for
(
const
auto
&
initializer
:
initializers
())
for
(
const
auto
&
initializer
:
initializers
())
initializer
(
m
);
initializer
(
m
);
if
(
!
m
.
attr
(
"have_eigen"
))
m
.
attr
(
"have_eigen"
)
=
py
::
cast
(
false
);
if
(
!
py
::
has
attr
(
m
,
"have_eigen"
))
m
.
attr
(
"have_eigen"
)
=
py
::
cast
(
false
);
return
m
.
ptr
();
return
m
.
ptr
();
}
}
tests/test_python_types.cpp
View file @
0a014e91
...
@@ -60,7 +60,7 @@ public:
...
@@ -60,7 +60,7 @@ public:
py
::
list
get_list
()
{
py
::
list
get_list
()
{
py
::
list
list
;
py
::
list
list
;
list
.
append
(
py
::
str
(
"value"
));
list
.
append
(
py
::
str
(
"value"
));
py
::
print
(
"Entry at position 0:"
,
py
::
object
(
list
[
0
])
)
;
py
::
print
(
"Entry at position 0:"
,
list
[
0
]);
list
[
0
]
=
py
::
str
(
"overwritten"
);
list
[
0
]
=
py
::
str
(
"overwritten"
);
return
list
;
return
list
;
}
}
...
@@ -203,7 +203,7 @@ test_initializer python_types([](py::module &m) {
...
@@ -203,7 +203,7 @@ test_initializer python_types([](py::module &m) {
py
::
print
(
"no new line here"
,
"end"
_a
=
" -- "
);
py
::
print
(
"no new line here"
,
"end"
_a
=
" -- "
);
py
::
print
(
"next print"
);
py
::
print
(
"next print"
);
auto
py_stderr
=
py
::
module
::
import
(
"sys"
).
attr
(
"stderr"
)
.
cast
<
py
::
object
>
()
;
auto
py_stderr
=
py
::
module
::
import
(
"sys"
).
attr
(
"stderr"
);
py
::
print
(
"this goes to stderr"
,
"file"
_a
=
py_stderr
);
py
::
print
(
"this goes to stderr"
,
"file"
_a
=
py_stderr
);
py
::
print
(
"flush"
,
"flush"
_a
=
true
);
py
::
print
(
"flush"
,
"flush"
_a
=
true
);
...
@@ -222,4 +222,71 @@ test_initializer python_types([](py::module &m) {
...
@@ -222,4 +222,71 @@ test_initializer python_types([](py::module &m) {
auto
d2
=
py
::
dict
(
"z"
_a
=
3
,
**
d1
);
auto
d2
=
py
::
dict
(
"z"
_a
=
3
,
**
d1
);
return
d2
;
return
d2
;
});
});
m
.
def
(
"test_accessor_api"
,
[](
py
::
object
o
)
{
auto
d
=
py
::
dict
();
d
[
"basic_attr"
]
=
o
.
attr
(
"basic_attr"
);
auto
l
=
py
::
list
();
for
(
const
auto
&
item
:
o
.
attr
(
"begin_end"
))
{
l
.
append
(
item
);
}
d
[
"begin_end"
]
=
l
;
d
[
"operator[object]"
]
=
o
.
attr
(
"d"
)[
"operator[object]"
_s
];
d
[
"operator[char *]"
]
=
o
.
attr
(
"d"
)[
"operator[char *]"
];
d
[
"attr(object)"
]
=
o
.
attr
(
"sub"
).
attr
(
"attr_obj"
);
d
[
"attr(char *)"
]
=
o
.
attr
(
"sub"
).
attr
(
"attr_char"
);
try
{
o
.
attr
(
"sub"
).
attr
(
"missing"
).
ptr
();
}
catch
(
const
py
::
error_already_set
&
)
{
d
[
"missing_attr_ptr"
]
=
"raised"
_s
;
}
try
{
o
.
attr
(
"missing"
).
attr
(
"doesn't matter"
);
}
catch
(
const
py
::
error_already_set
&
)
{
d
[
"missing_attr_chain"
]
=
"raised"
_s
;
}
d
[
"is_none"
]
=
py
::
cast
(
o
.
attr
(
"basic_attr"
).
is_none
());
d
[
"operator()"
]
=
o
.
attr
(
"func"
)(
1
);
d
[
"operator*"
]
=
o
.
attr
(
"func"
)(
*
o
.
attr
(
"begin_end"
));
return
d
;
});
m
.
def
(
"test_tuple_accessor"
,
[](
py
::
tuple
existing_t
)
{
try
{
existing_t
[
0
]
=
py
::
cast
(
1
);
}
catch
(
const
py
::
error_already_set
&
)
{
// --> Python system error
// Only new tuples (refcount == 1) are mutable
auto
new_t
=
py
::
tuple
(
3
);
for
(
size_t
i
=
0
;
i
<
new_t
.
size
();
++
i
)
{
new_t
[
i
]
=
py
::
cast
(
i
);
}
return
new_t
;
}
return
py
::
tuple
();
});
m
.
def
(
"test_accessor_assignment"
,
[]()
{
auto
l
=
py
::
list
(
1
);
l
[
0
]
=
py
::
cast
(
0
);
auto
d
=
py
::
dict
();
d
[
"get"
]
=
l
[
0
];
auto
var
=
l
[
0
];
d
[
"deferred_get"
]
=
var
;
l
[
0
]
=
py
::
cast
(
1
);
d
[
"set"
]
=
l
[
0
];
var
=
py
::
cast
(
99
);
// this assignment should not overwrite l[0]
d
[
"deferred_set"
]
=
l
[
0
];
d
[
"var"
]
=
var
;
return
d
;
});
});
});
tests/test_python_types.py
View file @
0a014e91
...
@@ -248,3 +248,42 @@ def test_dict_api():
...
@@ -248,3 +248,42 @@ def test_dict_api():
from
pybind11_tests
import
test_dict_keyword_constructor
from
pybind11_tests
import
test_dict_keyword_constructor
assert
test_dict_keyword_constructor
()
==
{
"x"
:
1
,
"y"
:
2
,
"z"
:
3
}
assert
test_dict_keyword_constructor
()
==
{
"x"
:
1
,
"y"
:
2
,
"z"
:
3
}
def
test_accessors
():
from
pybind11_tests
import
test_accessor_api
,
test_tuple_accessor
,
test_accessor_assignment
class
SubTestObject
:
attr_obj
=
1
attr_char
=
2
class
TestObject
:
basic_attr
=
1
begin_end
=
[
1
,
2
,
3
]
d
=
{
"operator[object]"
:
1
,
"operator[char *]"
:
2
}
sub
=
SubTestObject
()
def
func
(
self
,
x
,
*
args
):
return
self
.
basic_attr
+
x
+
sum
(
args
)
d
=
test_accessor_api
(
TestObject
())
assert
d
[
"basic_attr"
]
==
1
assert
d
[
"begin_end"
]
==
[
1
,
2
,
3
]
assert
d
[
"operator[object]"
]
==
1
assert
d
[
"operator[char *]"
]
==
2
assert
d
[
"attr(object)"
]
==
1
assert
d
[
"attr(char *)"
]
==
2
assert
d
[
"missing_attr_ptr"
]
==
"raised"
assert
d
[
"missing_attr_chain"
]
==
"raised"
assert
d
[
"is_none"
]
is
False
assert
d
[
"operator()"
]
==
2
assert
d
[
"operator*"
]
==
7
assert
test_tuple_accessor
(
tuple
())
==
(
0
,
1
,
2
)
d
=
test_accessor_assignment
()
assert
d
[
"get"
]
==
0
assert
d
[
"deferred_get"
]
==
0
assert
d
[
"set"
]
==
1
assert
d
[
"deferred_set"
]
==
1
assert
d
[
"var"
]
==
99
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