Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Olivier B.
pybind11
Commits
678d787c
Commit
678d787c
authored
Jan 17, 2016
by
Wenzel Jakob
Browse files
do more work with classes from pytypes.h (especially for STL container casting)
parent
d561cb01
Changes
10
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
678d787c
...
...
@@ -22,13 +22,13 @@ C++11-compatible compilers are widely available, this heavy machinery has
become an excessively large and unnecessary dependency.
Think of this library as a tiny self-contained version of Boost.Python with
everything stripped away that isn't relevant for binding generation.
The core
header files only require ~2.5K lines of code and depend on
Python (2.7 or 3.x)
and the C++ standard library. This compact implementation
was possible thanks
to some of the new C++11 language features (specifically:
tuples, lambda
functions and variadic templates). Since its creation, this
library has grown
beyond Boost.Python in many ways, leading to dramatically
simpler binding code
in many common situations.
everything stripped away that isn't relevant for binding generation.
Without
comments, the core
header files only require ~2.5K lines of code and depend on
Python (2.7 or 3.x)
and the C++ standard library. This compact implementation
was possible thanks
to some of the new C++11 language features (specifically:
tuples, lambda
functions and variadic templates). Since its creation, this
library has grown
beyond Boost.Python in many ways, leading to dramatically
simpler binding code
in many common situations.
Tutorial and reference documentation is provided at
[
http://pybind11.readthedocs.org/en/latest
](
http://pybind11.readthedocs.org/en/latest
)
.
...
...
docs/intro.rst
View file @
678d787c
...
...
@@ -19,13 +19,13 @@ C++11-compatible compilers are widely available, this heavy machinery has
become an excessively large and unnecessary dependency.
Think of this library as a tiny self-contained version of Boost.Python with
everything stripped away that isn't relevant for binding generation.
The core
header files only require ~2.5K lines of code and depend on
Python (2.7 or 3.x)
and the C++ standard library. This compact implementation
was possible thanks
to some of the new C++11 language features (specifically:
tuples, lambda
functions and variadic templates). Since its creation, this
library has grown
beyond Boost.Python in many ways, leading to dramatically
simpler binding code
in many common situations.
everything stripped away that isn't relevant for binding generation.
Without
comments, the core
header files only require ~2.5K lines of code and depend on
Python (2.7 or 3.x)
and the C++ standard library. This compact implementation
was possible thanks
to some of the new C++11 language features (specifically:
tuples, lambda
functions and variadic templates). Since its creation, this
library has grown
beyond Boost.Python in many ways, leading to dramatically
simpler binding code
in many common situations.
Core features
*************
...
...
example/example4.ref
View file @
678d787c
...
...
@@ -10,7 +10,7 @@ test_function(enum=1)
None
test_function(enum=2)
None
<class '
E
xample
4
.EMode'>
<class '
e
xample.EMode'>
EMode.EFirstMode
EMode.EFirstMode
Example4::test_function(enum=1)
...
...
example/run_test.py
View file @
678d787c
...
...
@@ -22,6 +22,8 @@ def sanitize(lines):
line
=
line
.
replace
(
'__builtin__'
,
'builtins'
)
line
=
line
.
replace
(
'example.'
,
''
)
line
=
line
.
replace
(
'unicode'
,
'str'
)
line
=
line
.
replace
(
'Example4.EMode'
,
'EMode'
)
line
=
line
.
replace
(
'example.EMode'
,
'EMode'
)
line
=
line
.
replace
(
'method of builtins.PyCapsule instance'
,
''
)
line
=
line
.
strip
()
if
sys
.
platform
==
'win32'
:
...
...
include/pybind11/common.h
View file @
678d787c
...
...
@@ -225,8 +225,8 @@ struct argument_entry {
/// Internal data struture used to track registered instances and types
struct
internals
{
std
::
unordered_map
<
const
void
*
,
void
*>
registered_types_cpp
;
// std::type_info* -> type_info
std
::
unordered_map
<
const
void
*
,
void
*>
registered_types_py
;
// PyTypeObject* -> type_info
std
::
unordered_map
<
const
void
*
,
void
*>
registered_instances
;
// void * -> PyObject*
std
::
unordered_map
<
const
void
*
,
void
*>
registered_types_py
;
// PyTypeObject* -> type_info
std
::
unordered_map
<
const
void
*
,
void
*>
registered_instances
;
// void * -> PyObject*
std
::
unordered_set
<
std
::
pair
<
const
PyObject
*
,
const
char
*>
,
overload_hash
>
inactive_overload_cache
;
};
...
...
@@ -271,4 +271,7 @@ struct error_already_set : public std::runtime_error { public: error_already_set
/// Thrown when pybind11::cast or handle::call fail due to a type casting error
struct
cast_error
:
public
std
::
runtime_error
{
public
:
cast_error
(
const
std
::
string
&
w
=
""
)
:
std
::
runtime_error
(
w
)
{}
};
PYBIND11_NOINLINE
inline
void
pybind11_fail
(
const
char
*
reason
)
{
throw
std
::
runtime_error
(
reason
);
}
PYBIND11_NOINLINE
inline
void
pybind11_fail
(
const
std
::
string
&
reason
)
{
throw
std
::
runtime_error
(
reason
);
}
NAMESPACE_END
(
pybind11
)
include/pybind11/pybind11.h
View file @
678d787c
...
...
@@ -24,7 +24,6 @@
#endif
#include
"cast.h"
#include
<iostream>
NAMESPACE_BEGIN
(
pybind11
)
...
...
@@ -196,9 +195,9 @@ protected:
a
.
value
,
return_value_policy
::
automatic
,
nullptr
);
if
(
obj
==
nullptr
)
throw
std
::
runtime_error
(
"arg(): could not convert default keyword "
"argument into a Python object (type not "
"registered yet?)"
);
pybind11_fail
(
"arg(): could not convert default keyword "
"argument into a Python object (type not "
"registered yet?)"
);
entry
->
args
.
emplace_back
(
a
.
name
,
a
.
descr
,
obj
);
}
...
...
@@ -490,7 +489,7 @@ protected:
}
else
if
(
c
==
'%'
)
{
const
std
::
type_info
*
t
=
types
[
type_index
++
];
if
(
!
t
)
throw
std
::
runtime_error
(
"Internal error while parsing type signature (1)"
);
pybind11_fail
(
"Internal error while parsing type signature (1)"
);
auto
it
=
registered_types
.
find
(
t
);
if
(
it
!=
registered_types
.
end
())
{
signature
+=
((
const
detail
::
type_info
*
)
it
->
second
)
->
type
->
tp_name
;
...
...
@@ -504,7 +503,7 @@ protected:
}
}
if
(
type_depth
!=
0
||
types
[
type_index
]
!=
nullptr
)
throw
std
::
runtime_error
(
"Internal error while parsing type signature (2)"
);
pybind11_fail
(
"Internal error while parsing type signature (2)"
);
#if !defined(PYBIND11_CPP14)
delete
[]
types
;
...
...
@@ -519,7 +518,7 @@ protected:
#endif
if
(
!
m_entry
->
args
.
empty
()
&&
(
int
)
m_entry
->
args
.
size
()
!=
args
)
throw
std
::
runtime_error
(
pybind11_fail
(
"cpp_function(): function
\"
"
+
std
::
string
(
m_entry
->
name
)
+
"
\"
takes "
+
std
::
to_string
(
args
)
+
" arguments, but "
+
std
::
to_string
(
m_entry
->
args
.
size
())
+
" pybind11::arg entries were specified!"
);
...
...
@@ -555,7 +554,7 @@ protected:
});
m_ptr
=
PyCFunction_New
(
m_entry
->
def
,
entry_capsule
.
ptr
());
if
(
!
m_ptr
)
throw
std
::
runtime_error
(
"cpp_function::cpp_function(): Could not allocate function object"
);
pybind11_fail
(
"cpp_function::cpp_function(): Could not allocate function object"
);
}
else
{
/* Append at the end of the overload chain */
m_ptr
=
m_entry
->
sibling
;
...
...
@@ -597,7 +596,7 @@ protected:
m_ptr
=
PyMethod_New
(
m_ptr
,
nullptr
,
entry
->
class_
);
#endif
if
(
!
m_ptr
)
throw
std
::
runtime_error
(
"cpp_function::cpp_function(): Could not allocate instance method object"
);
pybind11_fail
(
"cpp_function::cpp_function(): Could not allocate instance method object"
);
Py_DECREF
(
func
);
}
}
...
...
@@ -621,7 +620,7 @@ public:
m_ptr
=
Py_InitModule3
(
name
,
nullptr
,
doc
);
#endif
if
(
m_ptr
==
nullptr
)
throw
std
::
runtime_error
(
"Internal error in module::module()"
);
pybind11_fail
(
"Internal error in module::module()"
);
inc_ref
();
}
...
...
@@ -647,7 +646,7 @@ public:
static
module
import
(
const
char
*
name
)
{
PyObject
*
obj
=
PyImport_ImportModule
(
name
);
if
(
!
obj
)
throw
std
::
runtime_error
(
"Module
\"
"
+
std
::
string
(
name
)
+
"
\"
not found!"
);
pybind11_fail
(
"Module
\"
"
+
std
::
string
(
name
)
+
"
\"
not found!"
);
return
module
(
obj
,
false
);
}
};
...
...
@@ -668,7 +667,7 @@ public:
auto
type
=
(
PyHeapTypeObject
*
)
type_holder
.
ptr
();
if
(
!
type_holder
||
!
name
)
throw
std
::
runtime_error
(
"generic_type: unable to create type object!"
);
pybind11_fail
(
"generic_type: unable to create type object!"
);
/* Register supplemental type information in C++ dict */
auto
&
internals
=
get_internals
();
...
...
@@ -732,7 +731,7 @@ public:
}
if
(
PyType_Ready
(
&
type
->
ht_type
)
<
0
)
throw
std
::
runtime_error
(
"generic_type: PyType_Ready failed!"
);
pybind11_fail
(
"generic_type: PyType_Ready failed!"
);
m_ptr
=
type_holder
.
ptr
();
...
...
@@ -756,7 +755,7 @@ protected:
object
type_holder
(
PyType_Type
.
tp_alloc
(
&
PyType_Type
,
0
),
false
);
object
name
(
PYBIND11_FROM_STRING
(
name_
.
c_str
()),
false
);
if
(
!
type_holder
||
!
name
)
throw
std
::
runtime_error
(
"generic_type::metaclass(): unable to create type object!"
);
pybind11_fail
(
"generic_type::metaclass(): unable to create type object!"
);
auto
type
=
(
PyHeapTypeObject
*
)
type_holder
.
ptr
();
type
->
ht_name
=
name
.
release
();
...
...
@@ -767,7 +766,7 @@ protected:
~
Py_TPFLAGS_HAVE_GC
;
if
(
PyType_Ready
(
&
type
->
ht_type
)
<
0
)
throw
std
::
runtime_error
(
"generic_type::metaclass(): PyType_Ready failed!"
);
pybind11_fail
(
"generic_type::metaclass(): PyType_Ready failed!"
);
ob_type
=
(
PyTypeObject
*
)
type_holder
.
release
();
}
...
...
@@ -798,7 +797,7 @@ protected:
auto
&
registered_instances
=
detail
::
get_internals
().
registered_instances
;
auto
it
=
registered_instances
.
find
(
self
->
value
);
if
(
it
==
registered_instances
.
end
())
throw
std
::
runtime_error
(
"generic_type::dealloc(): Tried to deallocate unregistered instance!"
);
pybind11_fail
(
"generic_type::dealloc(): Tried to deallocate unregistered instance!"
);
registered_instances
.
erase
(
it
);
}
Py_XDECREF
(
self
->
parent
);
...
...
@@ -1096,14 +1095,12 @@ PYBIND11_NOINLINE inline void keep_alive_impl(int Nurse, int Patient, PyObject *
handle
patient
(
Patient
>
0
?
PyTuple_GetItem
(
arg
,
Patient
-
1
)
:
ret
);
if
(
!
nurse
||
!
patient
)
throw
std
::
runtime_error
(
"Could not activate keep_alive!"
);
pybind11_fail
(
"Could not activate keep_alive!"
);
cpp_function
disable_lifesupport
(
[
patient
](
handle
weakref
)
{
patient
.
dec_ref
();
weakref
.
dec_ref
();
});
weakref
wr
(
nurse
,
disable_lifesupport
);
if
(
!
wr
)
throw
std
::
runtime_error
(
"Could not allocate weak reference!"
);
patient
.
inc_ref
();
/* reference patient and leak the weak reference */
(
void
)
wr
.
release
();
...
...
@@ -1138,7 +1135,7 @@ template <typename InputType, typename OutputType> void implicitly_convertible()
auto
&
registered_types
=
detail
::
get_internals
().
registered_types_cpp
;
auto
it
=
registered_types
.
find
(
&
typeid
(
OutputType
));
if
(
it
==
registered_types
.
end
())
throw
std
::
runtime_error
(
"implicitly_convertible: Unable to find type "
+
type_id
<
OutputType
>
());
pybind11_fail
(
"implicitly_convertible: Unable to find type "
+
type_id
<
OutputType
>
());
((
detail
::
type_info
*
)
it
->
second
)
->
implicit_conversions
.
push_back
(
implicit_caster
);
}
...
...
@@ -1196,7 +1193,7 @@ inline function get_overload(const void *this_ptr, const char *name) {
#define PYBIND11_OVERLOAD_PURE(ret_type, class_name, name, ...) \
PYBIND11_OVERLOAD_INT(ret_type, class_name, name, __VA_ARGS__) \
throw std::runtime_error
("Tried to call pure virtual function \"" #name "\"");
pybind11::pybind11_fail
("Tried to call pure virtual function \"" #name "\"");
NAMESPACE_END
(
pybind11
)
...
...
include/pybind11/pytypes.h
View file @
678d787c
...
...
@@ -88,12 +88,12 @@ public:
iterator
(
PyObject
*
obj
,
bool
borrowed
=
false
)
:
object
(
obj
,
borrowed
)
{
++*
this
;
}
iterator
&
operator
++
()
{
if
(
ptr
())
value
=
object
(
PyIter_Next
(
ptr
()
),
false
);
value
=
object
(
PyIter_Next
(
m_
ptr
),
false
);
return
*
this
;
}
bool
operator
==
(
const
iterator
&
it
)
const
{
return
*
it
==
**
this
;
}
bool
operator
!=
(
const
iterator
&
it
)
const
{
return
*
it
!=
**
this
;
}
const
object
&
operator
*
()
const
{
return
value
;
}
const
handle
&
operator
*
()
const
{
return
value
;
}
bool
check
()
const
{
return
PyIter_Check
(
ptr
());
}
private:
object
value
;
...
...
@@ -127,10 +127,10 @@ public:
void
operator
=
(
const
handle
&
h
)
{
if
(
attr
)
{
if
(
PyObject_SetAttr
(
obj
,
key
,
(
PyObject
*
)
h
.
ptr
())
<
0
)
throw
std
::
runtime_error
(
"Unable to set object attribute"
);
pybind11_fail
(
"Unable to set object attribute"
);
}
else
{
if
(
PyObject_SetItem
(
obj
,
key
,
(
PyObject
*
)
h
.
ptr
())
<
0
)
throw
std
::
runtime_error
(
"Unable to set object item"
);
pybind11_fail
(
"Unable to set object item"
);
}
}
...
...
@@ -164,12 +164,12 @@ public:
void
operator
=
(
const
handle
&
o
)
{
o
.
inc_ref
();
// PyList_SetItem steals a reference
if
(
PyList_SetItem
(
list
,
(
ssize_t
)
index
,
(
PyObject
*
)
o
.
ptr
())
<
0
)
throw
std
::
runtime_error
(
"Unable to assign value in Python list!"
);
pybind11_fail
(
"Unable to assign value in Python list!"
);
}
operator
object
()
const
{
PyObject
*
result
=
PyList_GetItem
(
list
,
(
ssize_t
)
index
);
if
(
!
result
)
throw
std
::
runtime_error
(
"Unable to retrieve value from Python list!"
);
pybind11_fail
(
"Unable to retrieve value from Python list!"
);
return
object
(
result
,
true
);
}
private:
...
...
@@ -184,12 +184,12 @@ public:
void
operator
=
(
const
handle
&
o
)
{
o
.
inc_ref
();
// PyTuple_SetItem steals a reference
if
(
PyTuple_SetItem
(
tuple
,
(
ssize_t
)
index
,
(
PyObject
*
)
o
.
ptr
())
<
0
)
throw
std
::
runtime_error
(
"Unable to assign value in Python tuple!"
);
pybind11_fail
(
"Unable to assign value in Python tuple!"
);
}
operator
object
()
const
{
PyObject
*
result
=
PyTuple_GetItem
(
tuple
,
(
ssize_t
)
index
);
if
(
!
result
)
throw
std
::
runtime_error
(
"Unable to retrieve value from Python tuple!"
);
pybind11_fail
(
"Unable to retrieve value from Python tuple!"
);
return
object
(
result
,
true
);
}
private:
...
...
@@ -205,8 +205,8 @@ public:
pos
=
-
1
;
return
*
this
;
}
std
::
pair
<
object
,
object
>
operator
*
()
const
{
return
std
::
make_pair
(
object
(
key
,
true
),
object
(
value
,
true
)
);
std
::
pair
<
handle
,
handle
>
operator
*
()
const
{
return
std
::
make_pair
(
key
,
value
);
}
bool
operator
==
(
const
dict_iterator
&
it
)
const
{
return
it
.
pos
==
pos
;
}
bool
operator
!=
(
const
dict_iterator
&
it
)
const
{
return
it
.
pos
!=
pos
;
}
...
...
@@ -242,7 +242,10 @@ inline iterator handle::end() const { return iterator(nullptr); }
class
str
:
public
object
{
public:
PYBIND11_OBJECT_DEFAULT
(
str
,
object
,
PyUnicode_Check
)
str
(
const
std
::
string
&
s
)
:
object
(
PyUnicode_FromStringAndSize
(
s
.
c_str
(),
s
.
length
()),
false
)
{
}
str
(
const
std
::
string
&
s
)
:
object
(
PyUnicode_FromStringAndSize
(
s
.
c_str
(),
s
.
length
()),
false
)
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate string object!"
);
}
operator
std
::
string
()
const
{
#if PY_MAJOR_VERSION >= 3
...
...
@@ -250,7 +253,7 @@ public:
#else
object
temp
(
PyUnicode_AsUTF8String
(
m_ptr
),
false
);
if
(
temp
.
ptr
()
==
nullptr
)
throw
std
::
runtime_error
(
"Unable to extract string contents!"
);
pybind11_fail
(
"Unable to extract string contents!"
);
return
PyString_AsString
(
temp
.
ptr
());
#endif
}
...
...
@@ -270,14 +273,16 @@ public:
PYBIND11_OBJECT_DEFAULT
(
bytes
,
object
,
PYBIND11_BYTES_CHECK
)
bytes
(
const
std
::
string
&
s
)
:
object
(
PYBIND11_BYTES_FROM_STRING_AND_SIZE
(
s
.
data
(),
s
.
size
()),
false
)
{
}
:
object
(
PYBIND11_BYTES_FROM_STRING_AND_SIZE
(
s
.
data
(),
s
.
size
()),
false
)
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate bytes object!"
);
}
operator
std
::
string
()
const
{
char
*
buffer
;
ssize_t
length
;
int
err
=
PYBIND11_BYTES_AS_STRING_AND_SIZE
(
m_ptr
,
&
buffer
,
&
length
);
if
(
err
==
-
1
)
throw
std
::
runtime_error
(
"Unable to extract bytes contents!"
);
pybind11_fail
(
"Unable to extract bytes contents!"
);
return
std
::
string
(
buffer
,
length
);
}
};
...
...
@@ -306,6 +311,7 @@ public:
else
m_ptr
=
PyLong_FromUnsignedLongLong
((
unsigned
long
long
)
value
);
}
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate int object!"
);
}
template
<
typename
T
,
...
...
@@ -328,8 +334,12 @@ public:
class
float_
:
public
object
{
public:
PYBIND11_OBJECT_DEFAULT
(
float_
,
object
,
PyFloat_Check
)
float_
(
float
value
)
:
object
(
PyFloat_FromDouble
((
double
)
value
),
false
)
{
}
float_
(
double
value
)
:
object
(
PyFloat_FromDouble
((
double
)
value
),
false
)
{
}
float_
(
float
value
)
:
object
(
PyFloat_FromDouble
((
double
)
value
),
false
)
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate float object!"
);
}
float_
(
double
value
)
:
object
(
PyFloat_FromDouble
((
double
)
value
),
false
)
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate float object!"
);
}
operator
float
()
const
{
return
(
float
)
PyFloat_AsDouble
(
m_ptr
);
}
operator
double
()
const
{
return
(
double
)
PyFloat_AsDouble
(
m_ptr
);
}
};
...
...
@@ -337,7 +347,9 @@ public:
class
weakref
:
public
object
{
public:
PYBIND11_OBJECT_DEFAULT
(
weakref
,
object
,
PyWeakref_Check
)
weakref
(
handle
obj
,
handle
callback
=
handle
())
:
object
(
PyWeakref_NewRef
(
obj
.
ptr
(),
callback
.
ptr
()),
false
)
{
}
weakref
(
handle
obj
,
handle
callback
=
handle
())
:
object
(
PyWeakref_NewRef
(
obj
.
ptr
(),
callback
.
ptr
()),
false
)
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate weak reference!"
);
}
};
class
slice
:
public
object
{
...
...
@@ -346,6 +358,7 @@ public:
slice
(
ssize_t
start_
,
ssize_t
stop_
,
ssize_t
step_
)
{
int_
start
(
start_
),
stop
(
stop_
),
step
(
step_
);
m_ptr
=
PySlice_New
(
start
.
ptr
(),
stop
.
ptr
(),
step
.
ptr
());
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate slice object!"
);
}
bool
compute
(
ssize_t
length
,
ssize_t
*
start
,
ssize_t
*
stop
,
ssize_t
*
step
,
ssize_t
*
slicelength
)
const
{
return
PySlice_GetIndicesEx
((
PYBIND11_SLICE_OBJECT
*
)
m_ptr
,
length
,
...
...
@@ -357,10 +370,13 @@ class capsule : public object {
public:
PYBIND11_OBJECT_DEFAULT
(
capsule
,
object
,
PyCapsule_CheckExact
)
capsule
(
PyObject
*
obj
,
bool
borrowed
)
:
object
(
obj
,
borrowed
)
{
}
capsule
(
void
*
value
,
void
(
*
destruct
)(
PyObject
*
)
=
nullptr
)
:
object
(
PyCapsule_New
(
value
,
nullptr
,
destruct
),
false
)
{
}
capsule
(
void
*
value
,
void
(
*
destruct
)(
PyObject
*
)
=
nullptr
)
:
object
(
PyCapsule_New
(
value
,
nullptr
,
destruct
),
false
)
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate capsule object!"
);
}
template
<
typename
T
>
operator
T
*
()
const
{
T
*
result
=
static_cast
<
T
*>
(
PyCapsule_GetPointer
(
m_ptr
,
nullptr
));
if
(
!
result
)
throw
std
::
runtime_error
(
"Unable to extract capsule contents!"
);
if
(
!
result
)
pybind11_fail
(
"Unable to extract capsule contents!"
);
return
result
;
}
};
...
...
@@ -368,7 +384,9 @@ public:
class
tuple
:
public
object
{
public:
PYBIND11_OBJECT
(
tuple
,
object
,
PyTuple_Check
)
tuple
(
size_t
size
=
0
)
:
object
(
PyTuple_New
((
ssize_t
)
size
),
false
)
{
}
tuple
(
size_t
size
=
0
)
:
object
(
PyTuple_New
((
ssize_t
)
size
),
false
)
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate tuple object!"
);
}
size_t
size
()
const
{
return
(
size_t
)
PyTuple_Size
(
m_ptr
);
}
detail
::
tuple_accessor
operator
[](
size_t
index
)
const
{
return
detail
::
tuple_accessor
(
ptr
(),
index
);
}
};
...
...
@@ -376,7 +394,9 @@ public:
class
dict
:
public
object
{
public:
PYBIND11_OBJECT
(
dict
,
object
,
PyDict_Check
)
dict
()
:
object
(
PyDict_New
(),
false
)
{
}
dict
()
:
object
(
PyDict_New
(),
false
)
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate dict object!"
);
}
size_t
size
()
const
{
return
(
size_t
)
PyDict_Size
(
m_ptr
);
}
detail
::
dict_iterator
begin
()
const
{
return
(
++
detail
::
dict_iterator
(
ptr
(),
0
));
}
detail
::
dict_iterator
end
()
const
{
return
detail
::
dict_iterator
();
}
...
...
@@ -386,7 +406,9 @@ public:
class
list
:
public
object
{
public:
PYBIND11_OBJECT
(
list
,
object
,
PyList_Check
)
list
(
size_t
size
=
0
)
:
object
(
PyList_New
((
ssize_t
)
size
),
false
)
{
}
list
(
size_t
size
=
0
)
:
object
(
PyList_New
((
ssize_t
)
size
),
false
)
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate list object!"
);
}
size_t
size
()
const
{
return
(
size_t
)
PyList_Size
(
m_ptr
);
}
detail
::
list_accessor
operator
[](
size_t
index
)
const
{
return
detail
::
list_accessor
(
ptr
(),
index
);
}
void
append
(
const
object
&
object
)
const
{
PyList_Append
(
m_ptr
,
(
PyObject
*
)
object
.
ptr
());
}
...
...
@@ -395,10 +417,12 @@ public:
class
set
:
public
object
{
public:
PYBIND11_OBJECT
(
set
,
object
,
PySet_Check
)
set
()
:
object
(
PySet_New
(
nullptr
),
false
)
{
}
set
()
:
object
(
PySet_New
(
nullptr
),
false
)
{
if
(
!
m_ptr
)
pybind11_fail
(
"Could not allocate set object!"
);
}
size_t
size
()
const
{
return
(
size_t
)
PySet_Size
(
m_ptr
);
}
void
add
(
const
object
&
object
)
const
{
PySet_Add
(
m_ptr
,
(
PyObject
*
)
object
.
ptr
());
}
void
clear
()
const
{
PySet_Clear
(
ptr
()
);
}
bool
add
(
const
object
&
object
)
const
{
return
PySet_Add
(
m_ptr
,
(
PyObject
*
)
object
.
ptr
())
==
0
;
}
void
clear
()
const
{
PySet_Clear
(
m_
ptr
);
}
};
class
function
:
public
object
{
...
...
@@ -448,7 +472,7 @@ PYBIND11_NOINLINE inline detail::type_info* get_type_info(PyTypeObject *type) {
return
(
detail
::
type_info
*
)
it
->
second
;
type
=
type
->
tp_base
;
if
(
type
==
nullptr
)
throw
std
::
runtime_error
(
"pybind11::detail::get_type_info: unable to find type object!"
);
pybind11_fail
(
"pybind11::detail::get_type_info: unable to find type object!"
);
}
while
(
true
);
}
...
...
include/pybind11/stl.h
View file @
678d787c
...
...
@@ -14,7 +14,6 @@
#include
<set>
#include
<iostream>
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
...
...
@@ -28,14 +27,14 @@ template <typename Value, typename Alloc> struct type_caster<std::vector<Value,
typedef
type_caster
<
Value
>
value_conv
;
public:
bool
load
(
PyObject
*
src
,
bool
convert
)
{
if
(
!
PyList_Check
(
src
))
list
l
(
src
,
true
);
if
(
!
l
.
check
())
return
false
;
size_t
size
=
(
size_t
)
PyList_GET_SIZE
(
src
);
value
.
reserve
(
size
);
value
.
reserve
(
l
.
size
());
value
.
clear
();
value_conv
conv
;
for
(
size_t
i
=
0
;
i
<
size
;
++
i
)
{
if
(
!
conv
.
load
(
PyList_GetItem
(
src
,
(
ssize_t
)
i
),
convert
))
for
(
auto
it
:
l
)
{
if
(
!
conv
.
load
(
it
.
ptr
(
),
convert
))
return
false
;
value
.
push_back
((
Value
)
conv
);
}
...
...
@@ -43,17 +42,15 @@ public:
}
static
PyObject
*
cast
(
const
type
&
src
,
return_value_policy
policy
,
PyObject
*
parent
)
{
object
list
(
PyList_New
(
src
.
size
()),
false
);
if
(
!
list
)
return
nullptr
;
list
l
(
src
.
size
());
size_t
index
=
0
;
for
(
auto
const
&
value
:
src
)
{
object
value_
(
value_conv
::
cast
(
value
,
policy
,
parent
),
false
);
object
value_
(
value_conv
::
cast
(
value
,
policy
,
parent
),
false
);
if
(
!
value_
)
return
nullptr
;
PyList_SET_ITEM
(
l
ist
.
ptr
(),
index
++
,
value_
.
release
());
// steals a reference
PyList_SET_ITEM
(
l
.
ptr
(),
index
++
,
value_
.
release
());
// steals a reference
}
return
l
ist
.
release
();
return
l
.
release
();
}
PYBIND11_TYPE_CASTER
(
type
,
_
(
"list<"
)
+
value_conv
::
name
()
+
_
(
">"
));
};
...
...
@@ -68,8 +65,8 @@ public:
return
false
;
value
.
clear
();
key_conv
conv
;
for
(
const
object
&
o
:
s
)
{
if
(
!
conv
.
load
(
(
PyObject
*
)
o
.
ptr
(),
convert
))
for
(
auto
entry
:
s
)
{
if
(
!
conv
.
load
(
entry
.
ptr
(),
convert
))
return
false
;
value
.
insert
((
Key
)
conv
);
}
...
...
@@ -77,15 +74,13 @@ public:
}
static
PyObject
*
cast
(
const
type
&
src
,
return_value_policy
policy
,
PyObject
*
parent
)
{
object
set
(
PySet_New
(
nullptr
),
false
);
if
(
!
set
)
return
nullptr
;
pybind11
::
set
s
;
for
(
auto
const
&
value
:
src
)
{
object
value_
(
key_conv
::
cast
(
value
,
policy
,
parent
),
false
);
if
(
!
value_
||
PySet_Add
(
set
.
ptr
(),
value_
.
ptr
())
!=
0
)
if
(
!
value_
||
!
s
.
add
(
value
)
)
return
nullptr
;
}
return
s
et
.
release
();
return
s
.
release
();
}
PYBIND11_TYPE_CASTER
(
type
,
_
(
"set<"
)
+
key_conv
::
name
()
+
_
(
">"
));
};
...
...
@@ -97,16 +92,15 @@ public:
typedef
type_caster
<
Value
>
value_conv
;
bool
load
(
PyObject
*
src
,
bool
convert
)
{
if
(
!
PyDict_Check
(
src
))
dict
d
(
src
,
true
);
if
(
!
d
.
check
())
return
false
;
value
.
clear
();
PyObject
*
key_
,
*
value_
;
ssize_t
pos
=
0
;
key_conv
kconv
;
value_conv
vconv
;
while
(
PyDict_Next
(
src
,
&
pos
,
&
key_
,
&
value_
))
{
if
(
!
kconv
.
load
(
key_
,
convert
)
||
!
vconv
.
load
(
value_
,
convert
))
value
.
clear
();
for
(
auto
it
:
d
)
{
if
(
!
kconv
.
load
(
it
.
first
.
ptr
(),
convert
)
||
!
vconv
.
load
(
it
.
second
.
ptr
(),
convert
))
return
false
;
value
[(
Key
)
kconv
]
=
(
Value
)
vconv
;
}
...
...
@@ -114,16 +108,15 @@ public:
}
static
PyObject
*
cast
(
const
type
&
src
,
return_value_policy
policy
,
PyObject
*
parent
)
{
object
dict
(
PyDict_New
(),
false
);
if
(
!
dict
)
return
nullptr
;
dict
d
;
for
(
auto
const
&
kv
:
src
)
{
object
key
(
key_conv
::
cast
(
kv
.
first
,
policy
,
parent
),
false
);
object
value
(
value_conv
::
cast
(
kv
.
second
,
policy
,
parent
),
false
);
if
(
!
key
||
!
value
||
PyDict_SetItem
(
dict
.
ptr
(),
key
.
ptr
(),
value
.
ptr
())
!=
0
)
if
(
!
key
||
!
value
)
return
nullptr
;
d
[
key
]
=
value
;
}
return
d
ict
.
release
();
return
d
.
release
();
}
PYBIND11_TYPE_CASTER
(
type
,
_
(
"dict<"
)
+
key_conv
::
name
()
+
_
(
", "
)
+
value_conv
::
name
()
+
_
(
">"
));
...
...
@@ -131,7 +124,10 @@ public:
NAMESPACE_END
(
detail
)
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
object
&
obj
)
{
os
<<
(
std
::
string
)
obj
.
str
();
return
os
;
}
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
handle
&
obj
)
{
os
<<
(
std
::
string
)
obj
.
str
();
return
os
;
}
NAMESPACE_END
(
pybind11
)
...
...
include/pybind11/typeid.h
View file @
678d787c
...
...
@@ -11,6 +11,7 @@
#include
<cstdio>
#include
<cstdlib>
#if defined(__GNUG__)
#include
<cxxabi.h>
#endif
...
...
@@ -26,7 +27,7 @@ inline void erase_all(std::string &string, const std::string &search) {
}
}
inline
void
clean_type_id
(
std
::
string
&
name
)
{
PYBIND11_NOINLINE
inline
void
clean_type_id
(
std
::
string
&
name
)
{