mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-11 08:03:55 +00:00
do more work with classes from pytypes.h (especially for STL container casting)
This commit is contained in:
parent
d561cb010c
commit
678d787ca4
14
README.md
14
README.md
@ -22,13 +22,13 @@ C++11-compatible compilers are widely available, this heavy machinery has
|
|||||||
become an excessively large and unnecessary dependency.
|
become an excessively large and unnecessary dependency.
|
||||||
|
|
||||||
Think of this library as a tiny self-contained version of Boost.Python with
|
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
|
everything stripped away that isn't relevant for binding generation. Without
|
||||||
header files only require ~2.5K lines of code and depend on Python (2.7 or 3.x)
|
comments, the core header files only require ~2.5K lines of code and depend on
|
||||||
and the C++ standard library. This compact implementation was possible thanks
|
Python (2.7 or 3.x) and the C++ standard library. This compact implementation
|
||||||
to some of the new C++11 language features (specifically: tuples, lambda
|
was possible thanks to some of the new C++11 language features (specifically:
|
||||||
functions and variadic templates). Since its creation, this library has grown
|
tuples, lambda functions and variadic templates). Since its creation, this
|
||||||
beyond Boost.Python in many ways, leading to dramatically simpler binding code
|
library has grown beyond Boost.Python in many ways, leading to dramatically
|
||||||
in many common situations.
|
simpler binding code in many common situations.
|
||||||
|
|
||||||
Tutorial and reference documentation is provided at
|
Tutorial and reference documentation is provided at
|
||||||
[http://pybind11.readthedocs.org/en/latest](http://pybind11.readthedocs.org/en/latest).
|
[http://pybind11.readthedocs.org/en/latest](http://pybind11.readthedocs.org/en/latest).
|
||||||
|
@ -19,13 +19,13 @@ C++11-compatible compilers are widely available, this heavy machinery has
|
|||||||
become an excessively large and unnecessary dependency.
|
become an excessively large and unnecessary dependency.
|
||||||
|
|
||||||
Think of this library as a tiny self-contained version of Boost.Python with
|
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
|
everything stripped away that isn't relevant for binding generation. Without
|
||||||
header files only require ~2.5K lines of code and depend on Python (2.7 or 3.x)
|
comments, the core header files only require ~2.5K lines of code and depend on
|
||||||
and the C++ standard library. This compact implementation was possible thanks
|
Python (2.7 or 3.x) and the C++ standard library. This compact implementation
|
||||||
to some of the new C++11 language features (specifically: tuples, lambda
|
was possible thanks to some of the new C++11 language features (specifically:
|
||||||
functions and variadic templates). Since its creation, this library has grown
|
tuples, lambda functions and variadic templates). Since its creation, this
|
||||||
beyond Boost.Python in many ways, leading to dramatically simpler binding code
|
library has grown beyond Boost.Python in many ways, leading to dramatically
|
||||||
in many common situations.
|
simpler binding code in many common situations.
|
||||||
|
|
||||||
Core features
|
Core features
|
||||||
*************
|
*************
|
||||||
|
@ -10,7 +10,7 @@ test_function(enum=1)
|
|||||||
None
|
None
|
||||||
test_function(enum=2)
|
test_function(enum=2)
|
||||||
None
|
None
|
||||||
<class 'Example4.EMode'>
|
<class 'example.EMode'>
|
||||||
EMode.EFirstMode
|
EMode.EFirstMode
|
||||||
EMode.EFirstMode
|
EMode.EFirstMode
|
||||||
Example4::test_function(enum=1)
|
Example4::test_function(enum=1)
|
||||||
|
@ -22,6 +22,8 @@ def sanitize(lines):
|
|||||||
line = line.replace('__builtin__', 'builtins')
|
line = line.replace('__builtin__', 'builtins')
|
||||||
line = line.replace('example.', '')
|
line = line.replace('example.', '')
|
||||||
line = line.replace('unicode', 'str')
|
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.replace('method of builtins.PyCapsule instance', '')
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
|
@ -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
|
/// 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) {} };
|
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)
|
NAMESPACE_END(pybind11)
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "cast.h"
|
#include "cast.h"
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
NAMESPACE_BEGIN(pybind11)
|
NAMESPACE_BEGIN(pybind11)
|
||||||
|
|
||||||
@ -196,7 +195,7 @@ protected:
|
|||||||
a.value, return_value_policy::automatic, nullptr);
|
a.value, return_value_policy::automatic, nullptr);
|
||||||
|
|
||||||
if (obj == nullptr)
|
if (obj == nullptr)
|
||||||
throw std::runtime_error("arg(): could not convert default keyword "
|
pybind11_fail("arg(): could not convert default keyword "
|
||||||
"argument into a Python object (type not "
|
"argument into a Python object (type not "
|
||||||
"registered yet?)");
|
"registered yet?)");
|
||||||
|
|
||||||
@ -490,7 +489,7 @@ protected:
|
|||||||
} else if (c == '%') {
|
} else if (c == '%') {
|
||||||
const std::type_info *t = types[type_index++];
|
const std::type_info *t = types[type_index++];
|
||||||
if (!t)
|
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);
|
auto it = registered_types.find(t);
|
||||||
if (it != registered_types.end()) {
|
if (it != registered_types.end()) {
|
||||||
signature += ((const detail::type_info *) it->second)->type->tp_name;
|
signature += ((const detail::type_info *) it->second)->type->tp_name;
|
||||||
@ -504,7 +503,7 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type_depth != 0 || types[type_index] != nullptr)
|
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)
|
#if !defined(PYBIND11_CPP14)
|
||||||
delete[] types;
|
delete[] types;
|
||||||
@ -519,7 +518,7 @@ protected:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!m_entry->args.empty() && (int) m_entry->args.size() != args)
|
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 " +
|
"cpp_function(): function \"" + std::string(m_entry->name) + "\" takes " +
|
||||||
std::to_string(args) + " arguments, but " + std::to_string(m_entry->args.size()) +
|
std::to_string(args) + " arguments, but " + std::to_string(m_entry->args.size()) +
|
||||||
" pybind11::arg entries were specified!");
|
" pybind11::arg entries were specified!");
|
||||||
@ -555,7 +554,7 @@ protected:
|
|||||||
});
|
});
|
||||||
m_ptr = PyCFunction_New(m_entry->def, entry_capsule.ptr());
|
m_ptr = PyCFunction_New(m_entry->def, entry_capsule.ptr());
|
||||||
if (!m_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 {
|
} else {
|
||||||
/* Append at the end of the overload chain */
|
/* Append at the end of the overload chain */
|
||||||
m_ptr = m_entry->sibling;
|
m_ptr = m_entry->sibling;
|
||||||
@ -597,7 +596,7 @@ protected:
|
|||||||
m_ptr = PyMethod_New(m_ptr, nullptr, entry->class_);
|
m_ptr = PyMethod_New(m_ptr, nullptr, entry->class_);
|
||||||
#endif
|
#endif
|
||||||
if (!m_ptr)
|
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);
|
Py_DECREF(func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -621,7 +620,7 @@ public:
|
|||||||
m_ptr = Py_InitModule3(name, nullptr, doc);
|
m_ptr = Py_InitModule3(name, nullptr, doc);
|
||||||
#endif
|
#endif
|
||||||
if (m_ptr == nullptr)
|
if (m_ptr == nullptr)
|
||||||
throw std::runtime_error("Internal error in module::module()");
|
pybind11_fail("Internal error in module::module()");
|
||||||
inc_ref();
|
inc_ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,7 +646,7 @@ public:
|
|||||||
static module import(const char *name) {
|
static module import(const char *name) {
|
||||||
PyObject *obj = PyImport_ImportModule(name);
|
PyObject *obj = PyImport_ImportModule(name);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
throw std::runtime_error("Module \"" + std::string(name) + "\" not found!");
|
pybind11_fail("Module \"" + std::string(name) + "\" not found!");
|
||||||
return module(obj, false);
|
return module(obj, false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -668,7 +667,7 @@ public:
|
|||||||
auto type = (PyHeapTypeObject*) type_holder.ptr();
|
auto type = (PyHeapTypeObject*) type_holder.ptr();
|
||||||
|
|
||||||
if (!type_holder || !name)
|
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 */
|
/* Register supplemental type information in C++ dict */
|
||||||
auto &internals = get_internals();
|
auto &internals = get_internals();
|
||||||
@ -732,7 +731,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (PyType_Ready(&type->ht_type) < 0)
|
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();
|
m_ptr = type_holder.ptr();
|
||||||
|
|
||||||
@ -756,7 +755,7 @@ protected:
|
|||||||
object type_holder(PyType_Type.tp_alloc(&PyType_Type, 0), false);
|
object type_holder(PyType_Type.tp_alloc(&PyType_Type, 0), false);
|
||||||
object name(PYBIND11_FROM_STRING(name_.c_str()), false);
|
object name(PYBIND11_FROM_STRING(name_.c_str()), false);
|
||||||
if (!type_holder || !name)
|
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();
|
auto type = (PyHeapTypeObject*) type_holder.ptr();
|
||||||
type->ht_name = name.release();
|
type->ht_name = name.release();
|
||||||
@ -767,7 +766,7 @@ protected:
|
|||||||
~Py_TPFLAGS_HAVE_GC;
|
~Py_TPFLAGS_HAVE_GC;
|
||||||
|
|
||||||
if (PyType_Ready(&type->ht_type) < 0)
|
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();
|
ob_type = (PyTypeObject *) type_holder.release();
|
||||||
}
|
}
|
||||||
@ -798,7 +797,7 @@ protected:
|
|||||||
auto ®istered_instances = detail::get_internals().registered_instances;
|
auto ®istered_instances = detail::get_internals().registered_instances;
|
||||||
auto it = registered_instances.find(self->value);
|
auto it = registered_instances.find(self->value);
|
||||||
if (it == registered_instances.end())
|
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);
|
registered_instances.erase(it);
|
||||||
}
|
}
|
||||||
Py_XDECREF(self->parent);
|
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);
|
handle patient(Patient > 0 ? PyTuple_GetItem(arg, Patient - 1) : ret);
|
||||||
|
|
||||||
if (!nurse || !patient)
|
if (!nurse || !patient)
|
||||||
throw std::runtime_error("Could not activate keep_alive!");
|
pybind11_fail("Could not activate keep_alive!");
|
||||||
|
|
||||||
cpp_function disable_lifesupport(
|
cpp_function disable_lifesupport(
|
||||||
[patient](handle weakref) { patient.dec_ref(); weakref.dec_ref(); });
|
[patient](handle weakref) { patient.dec_ref(); weakref.dec_ref(); });
|
||||||
|
|
||||||
weakref wr(nurse, disable_lifesupport);
|
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 */
|
patient.inc_ref(); /* reference patient and leak the weak reference */
|
||||||
(void) wr.release();
|
(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 & registered_types = detail::get_internals().registered_types_cpp;
|
||||||
auto it = registered_types.find(&typeid(OutputType));
|
auto it = registered_types.find(&typeid(OutputType));
|
||||||
if (it == registered_types.end())
|
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);
|
((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, ...) \
|
#define PYBIND11_OVERLOAD_PURE(ret_type, class_name, name, ...) \
|
||||||
PYBIND11_OVERLOAD_INT(ret_type, class_name, name, __VA_ARGS__) \
|
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)
|
NAMESPACE_END(pybind11)
|
||||||
|
|
||||||
|
@ -88,12 +88,12 @@ public:
|
|||||||
iterator(PyObject *obj, bool borrowed = false) : object(obj, borrowed) { ++*this; }
|
iterator(PyObject *obj, bool borrowed = false) : object(obj, borrowed) { ++*this; }
|
||||||
iterator& operator++() {
|
iterator& operator++() {
|
||||||
if (ptr())
|
if (ptr())
|
||||||
value = object(PyIter_Next(ptr()), false);
|
value = object(PyIter_Next(m_ptr), false);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
bool operator==(const iterator &it) const { return *it == **this; }
|
bool operator==(const iterator &it) const { return *it == **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()); }
|
bool check() const { return PyIter_Check(ptr()); }
|
||||||
private:
|
private:
|
||||||
object value;
|
object value;
|
||||||
@ -127,10 +127,10 @@ public:
|
|||||||
void operator=(const handle &h) {
|
void operator=(const handle &h) {
|
||||||
if (attr) {
|
if (attr) {
|
||||||
if (PyObject_SetAttr(obj, key, (PyObject *) h.ptr()) < 0)
|
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 {
|
} else {
|
||||||
if (PyObject_SetItem(obj, key, (PyObject *) h.ptr()) < 0)
|
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) {
|
void operator=(const handle &o) {
|
||||||
o.inc_ref(); // PyList_SetItem steals a reference
|
o.inc_ref(); // PyList_SetItem steals a reference
|
||||||
if (PyList_SetItem(list, (ssize_t) index, (PyObject *) o.ptr()) < 0)
|
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 {
|
operator object() const {
|
||||||
PyObject *result = PyList_GetItem(list, (ssize_t) index);
|
PyObject *result = PyList_GetItem(list, (ssize_t) index);
|
||||||
if (!result)
|
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);
|
return object(result, true);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
@ -184,12 +184,12 @@ public:
|
|||||||
void operator=(const handle &o) {
|
void operator=(const handle &o) {
|
||||||
o.inc_ref(); // PyTuple_SetItem steals a reference
|
o.inc_ref(); // PyTuple_SetItem steals a reference
|
||||||
if (PyTuple_SetItem(tuple, (ssize_t) index, (PyObject *) o.ptr()) < 0)
|
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 {
|
operator object() const {
|
||||||
PyObject *result = PyTuple_GetItem(tuple, (ssize_t) index);
|
PyObject *result = PyTuple_GetItem(tuple, (ssize_t) index);
|
||||||
if (!result)
|
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);
|
return object(result, true);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
@ -205,8 +205,8 @@ public:
|
|||||||
pos = -1;
|
pos = -1;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
std::pair<object, object> operator*() const {
|
std::pair<handle, handle> operator*() const {
|
||||||
return std::make_pair(object(key, true), object(value, true));
|
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; }
|
||||||
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 {
|
class str : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT_DEFAULT(str, object, PyUnicode_Check)
|
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 {
|
operator std::string() const {
|
||||||
#if PY_MAJOR_VERSION >= 3
|
#if PY_MAJOR_VERSION >= 3
|
||||||
@ -250,7 +253,7 @@ public:
|
|||||||
#else
|
#else
|
||||||
object temp(PyUnicode_AsUTF8String(m_ptr), false);
|
object temp(PyUnicode_AsUTF8String(m_ptr), false);
|
||||||
if (temp.ptr() == nullptr)
|
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());
|
return PyString_AsString(temp.ptr());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -270,14 +273,16 @@ public:
|
|||||||
PYBIND11_OBJECT_DEFAULT(bytes, object, PYBIND11_BYTES_CHECK)
|
PYBIND11_OBJECT_DEFAULT(bytes, object, PYBIND11_BYTES_CHECK)
|
||||||
|
|
||||||
bytes(const std::string &s)
|
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 {
|
operator std::string() const {
|
||||||
char *buffer;
|
char *buffer;
|
||||||
ssize_t length;
|
ssize_t length;
|
||||||
int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(m_ptr, &buffer, &length);
|
int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(m_ptr, &buffer, &length);
|
||||||
if (err == -1)
|
if (err == -1)
|
||||||
throw std::runtime_error("Unable to extract bytes contents!");
|
pybind11_fail("Unable to extract bytes contents!");
|
||||||
return std::string(buffer, length);
|
return std::string(buffer, length);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -306,6 +311,7 @@ public:
|
|||||||
else
|
else
|
||||||
m_ptr = PyLong_FromUnsignedLongLong((unsigned long long) value);
|
m_ptr = PyLong_FromUnsignedLongLong((unsigned long long) value);
|
||||||
}
|
}
|
||||||
|
if (!m_ptr) pybind11_fail("Could not allocate int object!");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T,
|
template <typename T,
|
||||||
@ -328,8 +334,12 @@ public:
|
|||||||
class float_ : public object {
|
class float_ : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT_DEFAULT(float_, object, PyFloat_Check)
|
PYBIND11_OBJECT_DEFAULT(float_, object, PyFloat_Check)
|
||||||
float_(float value) : object(PyFloat_FromDouble((double) value), false) { }
|
float_(float value) : object(PyFloat_FromDouble((double) value), false) {
|
||||||
float_(double 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 float() const { return (float) PyFloat_AsDouble(m_ptr); }
|
||||||
operator double() const { return (double) PyFloat_AsDouble(m_ptr); }
|
operator double() const { return (double) PyFloat_AsDouble(m_ptr); }
|
||||||
};
|
};
|
||||||
@ -337,7 +347,9 @@ public:
|
|||||||
class weakref : public object {
|
class weakref : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT_DEFAULT(weakref, object, PyWeakref_Check)
|
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 {
|
class slice : public object {
|
||||||
@ -346,6 +358,7 @@ public:
|
|||||||
slice(ssize_t start_, ssize_t stop_, ssize_t step_) {
|
slice(ssize_t start_, ssize_t stop_, ssize_t step_) {
|
||||||
int_ start(start_), stop(stop_), step(step_);
|
int_ start(start_), stop(stop_), step(step_);
|
||||||
m_ptr = PySlice_New(start.ptr(), stop.ptr(), step.ptr());
|
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 {
|
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,
|
return PySlice_GetIndicesEx((PYBIND11_SLICE_OBJECT *) m_ptr, length,
|
||||||
@ -357,10 +370,13 @@ class capsule : public object {
|
|||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT_DEFAULT(capsule, object, PyCapsule_CheckExact)
|
PYBIND11_OBJECT_DEFAULT(capsule, object, PyCapsule_CheckExact)
|
||||||
capsule(PyObject *obj, bool borrowed) : object(obj, borrowed) { }
|
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 {
|
template <typename T> operator T *() const {
|
||||||
T * result = static_cast<T *>(PyCapsule_GetPointer(m_ptr, nullptr));
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -368,7 +384,9 @@ public:
|
|||||||
class tuple : public object {
|
class tuple : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT(tuple, object, PyTuple_Check)
|
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); }
|
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); }
|
detail::tuple_accessor operator[](size_t index) const { return detail::tuple_accessor(ptr(), index); }
|
||||||
};
|
};
|
||||||
@ -376,7 +394,9 @@ public:
|
|||||||
class dict : public object {
|
class dict : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT(dict, object, PyDict_Check)
|
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); }
|
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 begin() const { return (++detail::dict_iterator(ptr(), 0)); }
|
||||||
detail::dict_iterator end() const { return detail::dict_iterator(); }
|
detail::dict_iterator end() const { return detail::dict_iterator(); }
|
||||||
@ -386,7 +406,9 @@ public:
|
|||||||
class list : public object {
|
class list : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT(list, object, PyList_Check)
|
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); }
|
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); }
|
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()); }
|
void append(const object &object) const { PyList_Append(m_ptr, (PyObject *) object.ptr()); }
|
||||||
@ -395,10 +417,12 @@ public:
|
|||||||
class set : public object {
|
class set : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT(set, object, PySet_Check)
|
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); }
|
size_t size() const { return (size_t) PySet_Size(m_ptr); }
|
||||||
void add(const object &object) const { PySet_Add(m_ptr, (PyObject *) object.ptr()); }
|
bool add(const object &object) const { return PySet_Add(m_ptr, (PyObject *) object.ptr()) == 0; }
|
||||||
void clear() const { PySet_Clear(ptr()); }
|
void clear() const { PySet_Clear(m_ptr); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class function : public object {
|
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;
|
return (detail::type_info *) it->second;
|
||||||
type = type->tp_base;
|
type = type->tp_base;
|
||||||
if (type == nullptr)
|
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);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
|
#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;
|
typedef type_caster<Value> value_conv;
|
||||||
public:
|
public:
|
||||||
bool load(PyObject *src, bool convert) {
|
bool load(PyObject *src, bool convert) {
|
||||||
if (!PyList_Check(src))
|
list l(src, true);
|
||||||
|
if (!l.check())
|
||||||
return false;
|
return false;
|
||||||
size_t size = (size_t) PyList_GET_SIZE(src);
|
value.reserve(l.size());
|
||||||
value.reserve(size);
|
|
||||||
value.clear();
|
value.clear();
|
||||||
value_conv conv;
|
value_conv conv;
|
||||||
for (size_t i=0; i<size; ++i) {
|
for (auto it : l) {
|
||||||
if (!conv.load(PyList_GetItem(src, (ssize_t) i), convert))
|
if (!conv.load(it.ptr(), convert))
|
||||||
return false;
|
return false;
|
||||||
value.push_back((Value) conv);
|
value.push_back((Value) conv);
|
||||||
}
|
}
|
||||||
@ -43,17 +42,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
|
static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
|
||||||
object list(PyList_New(src.size()), false);
|
list l(src.size());
|
||||||
if (!list)
|
|
||||||
return nullptr;
|
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
for (auto const &value: src) {
|
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_)
|
if (!value_)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
PyList_SET_ITEM(list.ptr(), index++, value_.release()); // steals a reference
|
PyList_SET_ITEM(l.ptr(), index++, value_.release()); // steals a reference
|
||||||
}
|
}
|
||||||
return list.release();
|
return l.release();
|
||||||
}
|
}
|
||||||
PYBIND11_TYPE_CASTER(type, _("list<") + value_conv::name() + _(">"));
|
PYBIND11_TYPE_CASTER(type, _("list<") + value_conv::name() + _(">"));
|
||||||
};
|
};
|
||||||
@ -68,8 +65,8 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
value.clear();
|
value.clear();
|
||||||
key_conv conv;
|
key_conv conv;
|
||||||
for (const object &o: s) {
|
for (auto entry : s) {
|
||||||
if (!conv.load((PyObject *) o.ptr(), convert))
|
if (!conv.load(entry.ptr(), convert))
|
||||||
return false;
|
return false;
|
||||||
value.insert((Key) conv);
|
value.insert((Key) conv);
|
||||||
}
|
}
|
||||||
@ -77,15 +74,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
|
static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
|
||||||
object set(PySet_New(nullptr), false);
|
pybind11::set s;
|
||||||
if (!set)
|
|
||||||
return nullptr;
|
|
||||||
for (auto const &value: src) {
|
for (auto const &value: src) {
|
||||||
object value_(key_conv::cast(value, policy, parent), false);
|
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 nullptr;
|
||||||
}
|
}
|
||||||
return set.release();
|
return s.release();
|
||||||
}
|
}
|
||||||
PYBIND11_TYPE_CASTER(type, _("set<") + key_conv::name() + _(">"));
|
PYBIND11_TYPE_CASTER(type, _("set<") + key_conv::name() + _(">"));
|
||||||
};
|
};
|
||||||
@ -97,16 +92,15 @@ public:
|
|||||||
typedef type_caster<Value> value_conv;
|
typedef type_caster<Value> value_conv;
|
||||||
|
|
||||||
bool load(PyObject *src, bool convert) {
|
bool load(PyObject *src, bool convert) {
|
||||||
if (!PyDict_Check(src))
|
dict d(src, true);
|
||||||
|
if (!d.check())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
value.clear();
|
|
||||||
PyObject *key_, *value_;
|
|
||||||
ssize_t pos = 0;
|
|
||||||
key_conv kconv;
|
key_conv kconv;
|
||||||
value_conv vconv;
|
value_conv vconv;
|
||||||
while (PyDict_Next(src, &pos, &key_, &value_)) {
|
value.clear();
|
||||||
if (!kconv.load(key_, convert) || !vconv.load(value_, convert))
|
for (auto it : d) {
|
||||||
|
if (!kconv.load(it.first.ptr(), convert) ||
|
||||||
|
!vconv.load(it.second.ptr(), convert))
|
||||||
return false;
|
return false;
|
||||||
value[(Key) kconv] = (Value) vconv;
|
value[(Key) kconv] = (Value) vconv;
|
||||||
}
|
}
|
||||||
@ -114,16 +108,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
|
static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
|
||||||
object dict(PyDict_New(), false);
|
dict d;
|
||||||
if (!dict)
|
|
||||||
return nullptr;
|
|
||||||
for (auto const &kv: src) {
|
for (auto const &kv: src) {
|
||||||
object key(key_conv::cast(kv.first, policy, parent), false);
|
object key(key_conv::cast(kv.first, policy, parent), false);
|
||||||
object value(value_conv::cast(kv.second, 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;
|
return nullptr;
|
||||||
|
d[key] = value;
|
||||||
}
|
}
|
||||||
return dict.release();
|
return d.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_TYPE_CASTER(type, _("dict<") + key_conv::name() + _(", ") + value_conv::name() + _(">"));
|
PYBIND11_TYPE_CASTER(type, _("dict<") + key_conv::name() + _(", ") + value_conv::name() + _(">"));
|
||||||
@ -131,7 +124,10 @@ public:
|
|||||||
|
|
||||||
NAMESPACE_END(detail)
|
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)
|
NAMESPACE_END(pybind11)
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#if defined(__GNUG__)
|
#if defined(__GNUG__)
|
||||||
#include <cxxabi.h>
|
#include <cxxabi.h>
|
||||||
#endif
|
#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) {
|
||||||
#if defined(__GNUG__)
|
#if defined(__GNUG__)
|
||||||
int status = 0;
|
int status = 0;
|
||||||
std::unique_ptr<char, void (*)(void *)> res {
|
std::unique_ptr<char, void (*)(void *)> res {
|
||||||
|
16
setup.py
16
setup.py
@ -17,6 +17,7 @@ setup(
|
|||||||
headers=[
|
headers=[
|
||||||
'include/pybind11/cast.h',
|
'include/pybind11/cast.h',
|
||||||
'include/pybind11/complex.h',
|
'include/pybind11/complex.h',
|
||||||
|
'include/pybind11/descr.h',
|
||||||
'include/pybind11/numpy.h',
|
'include/pybind11/numpy.h',
|
||||||
'include/pybind11/pybind11.h',
|
'include/pybind11/pybind11.h',
|
||||||
'include/pybind11/stl.h',
|
'include/pybind11/stl.h',
|
||||||
@ -57,11 +58,10 @@ C++11-compatible compilers are widely available, this heavy machinery has
|
|||||||
become an excessively large and unnecessary dependency.
|
become an excessively large and unnecessary dependency.
|
||||||
|
|
||||||
Think of this library as a tiny self-contained version of Boost.Python with
|
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 whole
|
everything stripped away that isn't relevant for binding generation. The core
|
||||||
codebase requires less than 3000 lines of code and only depends on Python (2.7
|
header files only require ~2.5K lines of code and depend on Python (2.7 or 3.x)
|
||||||
or 3.x) and the C++ standard library. This compact implementation was
|
and the C++ standard library. This compact implementation was possible thanks
|
||||||
possible thanks to some of the new C++11 language features (tuples, lambda
|
to some of the new C++11 language features (specifically: tuples, lambda
|
||||||
functions and variadic templates). Since its creation, this library has
|
functions and variadic templates). Since its creation, this library has grown
|
||||||
grown beyond Boost.Python in many ways, leading to dramatically simpler binding
|
beyond Boost.Python in many ways, leading to dramatically simpler binding code
|
||||||
code in many common situations.""",
|
in many common situations.""")
|
||||||
)
|
|
||||||
|
Loading…
Reference in New Issue
Block a user