mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
added new type pybind11::bytes, cleanup of various macros (fixes #49)
This commit is contained in:
parent
2dfbadee5d
commit
27e8e1066b
@ -801,9 +801,9 @@ For instance, the following statement iterates over a Python ``dict``:
|
||||
}
|
||||
|
||||
Available types include :class:`handle`, :class:`object`, :class:`bool_`,
|
||||
:class:`int_`, :class:`float_`, :class:`str`, :class:`tuple`, :class:`list`,
|
||||
:class:`dict`, :class:`slice`, :class:`capsule`, :class:`function`,
|
||||
:class:`buffer`, :class:`array`, and :class:`array_t`.
|
||||
:class:`int_`, :class:`float_`, :class:`str`, :class:`bytes`, :class:`tuple`,
|
||||
:class:`list`, :class:`dict`, :class:`slice`, :class:`capsule`,
|
||||
:class:`function`, :class:`buffer`, :class:`array`, and :class:`array_t`.
|
||||
|
||||
In this kind of mixed code, it is often necessary to convert arbitrary C++
|
||||
types to Python, which can be done using :func:`cast`:
|
||||
|
@ -72,24 +72,12 @@ public:
|
||||
std::cout << "key: " << item.first << ", value=" << item.second << std::endl;
|
||||
}
|
||||
|
||||
/* STL data types are automatically casted from Python */
|
||||
void print_dict_2(const std::map<std::string, std::string> &dict) {
|
||||
for (auto item : dict)
|
||||
std::cout << "key: " << item.first << ", value=" << item.second << std::endl;
|
||||
}
|
||||
|
||||
/* Easily iterate over a setionary using a C++11 range-based for loop */
|
||||
/* Easily iterate over a set using a C++11 range-based for loop */
|
||||
void print_set(py::set set) {
|
||||
for (auto item : set)
|
||||
std::cout << "key: " << item << std::endl;
|
||||
}
|
||||
|
||||
/* STL data types are automatically casted from Python */
|
||||
void print_set_2(const std::set<std::string> &set) {
|
||||
for (auto item : set)
|
||||
std::cout << "key: " << item << std::endl;
|
||||
}
|
||||
|
||||
/* Easily iterate over a list using a C++11 range-based for loop */
|
||||
void print_list(py::list list) {
|
||||
int index = 0;
|
||||
@ -97,7 +85,19 @@ public:
|
||||
std::cout << "list item " << index++ << ": " << item << std::endl;
|
||||
}
|
||||
|
||||
/* STL data types are automatically casted from Python */
|
||||
/* STL data types (such as maps) are automatically casted from Python */
|
||||
void print_dict_2(const std::map<std::string, std::string> &dict) {
|
||||
for (auto item : dict)
|
||||
std::cout << "key: " << item.first << ", value=" << item.second << std::endl;
|
||||
}
|
||||
|
||||
/* STL data types (such as sets) are automatically casted from Python */
|
||||
void print_set_2(const std::set<std::string> &set) {
|
||||
for (auto item : set)
|
||||
std::cout << "key: " << item << std::endl;
|
||||
}
|
||||
|
||||
/* STL data types (such as vectors) are automatically casted from Python */
|
||||
void print_list_2(std::vector<std::string> &list) {
|
||||
int index = 0;
|
||||
for (auto item : list)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
example/example4.cpp -- global constants and functions, enumerations
|
||||
example/example4.cpp -- global constants and functions, enumerations, raw byte strings
|
||||
|
||||
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
|
||||
|
||||
@ -40,6 +40,17 @@ float test_function3(int i) {
|
||||
return i / 2.f;
|
||||
}
|
||||
|
||||
py::bytes return_bytes() {
|
||||
const char *data = "\x01\x00\x02\x00";
|
||||
return py::bytes(std::string(data, 4));
|
||||
}
|
||||
|
||||
void print_bytes(py::bytes bytes) {
|
||||
std::string value = (std::string) bytes;
|
||||
for (size_t i = 0; i < value.length(); ++i)
|
||||
std::cout << "bytes[" << i << "]=" << (int) value[i] << std::endl;
|
||||
}
|
||||
|
||||
void init_ex4(py::module &m) {
|
||||
m.def("test_function", &test_function1);
|
||||
m.def("test_function", &test_function2);
|
||||
@ -57,4 +68,7 @@ void init_ex4(py::module &m) {
|
||||
.value("EFirstMode", Example4::EFirstMode)
|
||||
.value("ESecondMode", Example4::ESecondMode)
|
||||
.export_values();
|
||||
|
||||
m.def("return_bytes", &return_bytes);
|
||||
m.def("print_bytes", &print_bytes);
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ from example import some_constant
|
||||
from example import EMyEnumeration
|
||||
from example import EFirstEntry
|
||||
from example import Example4
|
||||
from example import return_bytes
|
||||
from example import print_bytes
|
||||
|
||||
print(EMyEnumeration)
|
||||
print(EMyEnumeration.EFirstEntry)
|
||||
@ -23,3 +25,5 @@ print(Example4.EMode)
|
||||
print(Example4.EMode.EFirstMode)
|
||||
print(Example4.EFirstMode)
|
||||
Example4.test_function(Example4.EFirstMode)
|
||||
|
||||
print_bytes(return_bytes())
|
||||
|
@ -14,3 +14,7 @@ None
|
||||
EMode.EFirstMode
|
||||
EMode.EFirstMode
|
||||
Example4::test_function(enum=1)
|
||||
bytes[0]=1
|
||||
bytes[1]=0
|
||||
bytes[2]=2
|
||||
bytes[3]=0
|
||||
|
@ -21,6 +21,7 @@ def sanitize(lines):
|
||||
line = shorten_floats.sub(r'\1', line)
|
||||
line = line.replace('__builtin__', 'builtins')
|
||||
line = line.replace('example.', '')
|
||||
line = line.replace('unicode', 'str')
|
||||
line = line.replace('method of builtins.PyCapsule instance', '')
|
||||
line = line.strip()
|
||||
if sys.platform == 'win32':
|
||||
|
@ -19,12 +19,6 @@
|
||||
NAMESPACE_BEGIN(pybind11)
|
||||
NAMESPACE_BEGIN(detail)
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
#define PYBIND11_AS_STRING PyBytes_AsString
|
||||
#else
|
||||
#define PYBIND11_AS_STRING PyString_AsString
|
||||
#endif
|
||||
|
||||
class type_caster_custom {
|
||||
public:
|
||||
PYBIND11_NOINLINE type_caster_custom(const std::type_info *type_info) {
|
||||
@ -185,9 +179,9 @@ public:
|
||||
py_value = (py_type) PyLong_AsUnsignedLong(src);
|
||||
} else {
|
||||
if (std::is_signed<T>::value)
|
||||
py_value = (py_type) detail::PyLong_AsLongLong_(src);
|
||||
py_value = (py_type) PYBIND11_LONG_AS_LONGLONG(src);
|
||||
else
|
||||
py_value = (py_type) detail::PyLong_AsUnsignedLongLong_(src);
|
||||
py_value = (py_type) PYBIND11_LONG_AS_UNSIGNED_LONGLONG(src);
|
||||
}
|
||||
|
||||
if ((py_value == (py_type) -1 && PyErr_Occurred()) ||
|
||||
@ -265,35 +259,41 @@ public:
|
||||
template <> class type_caster<std::string> {
|
||||
public:
|
||||
bool load(PyObject *src, bool) {
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
if (PyString_Check(src)) { value = PyString_AsString(src); return true; }
|
||||
#endif
|
||||
object temp(PyUnicode_AsUTF8String(src), false);
|
||||
const char *ptr = nullptr;
|
||||
if (temp)
|
||||
ptr = PYBIND11_AS_STRING(temp.ptr());
|
||||
if (!ptr) { PyErr_Clear(); return false; }
|
||||
value = ptr;
|
||||
object temp;
|
||||
PyObject *load_src = src;
|
||||
if (PyUnicode_Check(src)) {
|
||||
temp = object(PyUnicode_AsUTF8String(src), false);
|
||||
if (!temp) { PyErr_Clear(); return false; } // UnicodeEncodeError
|
||||
load_src = temp.ptr();
|
||||
}
|
||||
char *buffer;
|
||||
ssize_t length;
|
||||
int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(load_src, &buffer, &length);
|
||||
if (err == -1) { PyErr_Clear(); return false; } // TypeError
|
||||
value = std::string(buffer, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
static PyObject *cast(const std::string &src, return_value_policy /* policy */, PyObject * /* parent */) {
|
||||
return PyUnicode_FromString(src.c_str());
|
||||
return PyUnicode_FromStringAndSize(src.c_str(), src.length());
|
||||
}
|
||||
PYBIND11_TYPE_CASTER(std::string, _("str"));
|
||||
|
||||
PYBIND11_TYPE_CASTER(std::string, _(PYBIND11_STRING_NAME));
|
||||
};
|
||||
|
||||
template <> class type_caster<char> {
|
||||
public:
|
||||
bool load(PyObject *src, bool) {
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
if (PyString_Check(src)) { value = PyString_AsString(src); return true; }
|
||||
#endif
|
||||
object temp(PyUnicode_AsUTF8String(src), false);
|
||||
const char *ptr = nullptr;
|
||||
if (temp)
|
||||
ptr = PYBIND11_AS_STRING(temp.ptr());
|
||||
if (!ptr) { PyErr_Clear(); return false; }
|
||||
value = ptr;
|
||||
object temp;
|
||||
PyObject *load_src = src;
|
||||
if (PyUnicode_Check(src)) {
|
||||
temp = object(PyUnicode_AsUTF8String(src), false);
|
||||
if (!temp) { PyErr_Clear(); return false; } // UnicodeEncodeError
|
||||
load_src = temp.ptr();
|
||||
}
|
||||
const char *ptr = PYBIND11_BYTES_AS_STRING(load_src);
|
||||
if (!ptr) { PyErr_Clear(); return false; } // TypeError
|
||||
value = std::string(ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -306,10 +306,10 @@ public:
|
||||
return PyUnicode_DecodeLatin1(str, 1, nullptr);
|
||||
}
|
||||
|
||||
static PYBIND11_DESCR name() { return type_descr(_("str")); }
|
||||
|
||||
operator char*() { return (char *) value.c_str(); }
|
||||
operator char() { if (value.length() > 0) return value[0]; else return '\0'; }
|
||||
|
||||
static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); }
|
||||
protected:
|
||||
std::string value;
|
||||
};
|
||||
|
@ -85,6 +85,29 @@
|
||||
} \
|
||||
PyObject *pybind11_init()
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3 /// Compatibility macros for various Python versions
|
||||
#define PYBIND11_BYTES_CHECK PyBytes_Check
|
||||
#define PYBIND11_BYTES_FROM_STRING PyBytes_FromString
|
||||
#define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyBytes_FromStringAndSize
|
||||
#define PYBIND11_BYTES_AS_STRING_AND_SIZE PyBytes_AsStringAndSize
|
||||
#define PYBIND11_BYTES_AS_STRING PyBytes_AsString
|
||||
#define PYBIND11_LONG_CHECK(o) PyLong_Check(o)
|
||||
#define PYBIND11_LONG_AS_LONGLONG(o) PyLong_AsLongLong(o)
|
||||
#define PYBIND11_LONG_AS_UNSIGNED_LONGLONG(o) PyLong_AsUnsignedLongLong(o)
|
||||
#define PYBIND11_STRING_NAME "str"
|
||||
#define PYBIND11_SLICE_OBJECT PyObject
|
||||
#else
|
||||
#define PYBIND11_BYTES_CHECK PyString_Check
|
||||
#define PYBIND11_BYTES_FROM_STRING PyString_FromString
|
||||
#define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyString_FromStringAndSize
|
||||
#define PYBIND11_BYTES_AS_STRING_AND_SIZE PyString_AsStringAndSize
|
||||
#define PYBIND11_BYTES_AS_STRING PyString_AsString
|
||||
#define PYBIND11_LONG_CHECK(o) (PyInt_Check(o) || PyLong_Check(o))
|
||||
#define PYBIND11_LONG_AS_LONGLONG(o) (PyInt_Check(o) ? (long long) PyLong_AsLong(o) : PyLong_AsLongLong(o))
|
||||
#define PYBIND11_LONG_AS_UNSIGNED_LONGLONG(o) (PyInt_Check(o) ? (unsigned long long) PyLong_AsUnsignedLong(o) : PyLong_AsUnsignedLongLong(o))
|
||||
#define PYBIND11_STRING_NAME "unicode"
|
||||
#define PYBIND11_SLICE_OBJECT PySliceObject
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(pybind11)
|
||||
|
||||
|
@ -337,7 +337,7 @@ private:
|
||||
if (a.descr)
|
||||
a.descr = strdup(a.descr);
|
||||
else if (a.value)
|
||||
a.descr = strdup(((object) handle(a.value).attr("__repr__")).call().str());
|
||||
a.descr = strdup(((std::string) ((object) handle(a.value).attr("__repr__")).call().str()).c_str());
|
||||
}
|
||||
auto const ®istered_types = detail::get_internals().registered_types;
|
||||
|
||||
@ -367,7 +367,7 @@ private:
|
||||
} else if (c == '%') {
|
||||
const std::type_info *t = types[type_index++];
|
||||
if (!t)
|
||||
throw std::runtime_error("Internal error while generating type signature (1)");
|
||||
throw std::runtime_error("Internal error while parsing type signature (1)");
|
||||
auto it = registered_types.find(t);
|
||||
if (it != registered_types.end()) {
|
||||
signature += it->second.type->tp_name;
|
||||
@ -381,7 +381,7 @@ private:
|
||||
}
|
||||
}
|
||||
if (type_depth != 0 && types[type_index ] != nullptr)
|
||||
throw std::runtime_error("Internal error while generating type signature (2)");
|
||||
throw std::runtime_error("Internal error while parsing type signature (2)");
|
||||
|
||||
#if !defined(PYBIND11_CPP14)
|
||||
delete[] types;
|
||||
@ -694,8 +694,8 @@ protected:
|
||||
view->format = const_cast<char *>(info->format.c_str());
|
||||
if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
|
||||
view->ndim = info->ndim;
|
||||
view->strides = (Py_ssize_t *)&info->strides[0];
|
||||
view->shape = (Py_ssize_t *) &info->shape[0];
|
||||
view->strides = (ssize_t *) &info->strides[0];
|
||||
view->shape = (ssize_t *) &info->shape[0];
|
||||
}
|
||||
Py_INCREF(view->obj);
|
||||
return 0;
|
||||
@ -903,7 +903,7 @@ public:
|
||||
void export_values() {
|
||||
PyObject *dict = ((PyTypeObject *) this->m_ptr)->tp_dict;
|
||||
PyObject *key, *value;
|
||||
Py_ssize_t pos = 0;
|
||||
ssize_t pos = 0;
|
||||
while (PyDict_Next(dict, &pos, &key, &value))
|
||||
if (PyObject_IsInstance(value, this->m_ptr))
|
||||
m_parent.attr(key) = value;
|
||||
@ -983,9 +983,10 @@ inline function get_overload(const void *this_ptr, const char *name) {
|
||||
cache.insert(key);
|
||||
return function();
|
||||
}
|
||||
|
||||
PyFrameObject *frame = PyThreadState_Get()->frame;
|
||||
pybind11::str caller = pybind11::handle(frame->f_code->co_name).str();
|
||||
if (strcmp((const char *) caller, name) == 0)
|
||||
if ((std::string) caller == name)
|
||||
return function();
|
||||
return overload;
|
||||
}
|
||||
|
@ -215,30 +215,6 @@ private:
|
||||
ssize_t pos = 0;
|
||||
};
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
inline long long PyLong_AsLongLong_(PyObject *o) { return PyLong_AsLongLong(o); }
|
||||
inline unsigned long long PyLong_AsUnsignedLongLong_(PyObject *o) { return PyLong_AsUnsignedLongLong(o); }
|
||||
inline bool PyLong_Check_(PyObject *o) { return PyLong_Check(o); }
|
||||
#else
|
||||
inline long long PyLong_AsLongLong_(PyObject *o) {
|
||||
if (PyInt_Check(o)) /// workaround: PyLong_AsLongLong doesn't accept 'int' on Python 2.x
|
||||
return (long long) PyLong_AsLong(o);
|
||||
else
|
||||
return PyLong_AsLongLong(o);
|
||||
}
|
||||
|
||||
inline unsigned long long PyLong_AsUnsignedLongLong_(PyObject *o) {
|
||||
if (PyInt_Check(o)) /// workaround: PyLong_AsUnsignedLongLong doesn't accept 'int' on Python 2.x
|
||||
return (unsigned long long) PyLong_AsUnsignedLong(o);
|
||||
else
|
||||
return PyLong_AsUnsignedLongLong(o);
|
||||
}
|
||||
|
||||
inline bool PyLong_Check_(PyObject *o) {
|
||||
return PyInt_Check(o) || PyLong_Check(o);
|
||||
}
|
||||
#endif
|
||||
|
||||
NAMESPACE_END(detail)
|
||||
|
||||
inline detail::accessor handle::operator[](handle key) const { return detail::accessor(ptr(), key.ptr(), false); }
|
||||
@ -266,21 +242,18 @@ inline iterator handle::end() const { return iterator(nullptr); }
|
||||
class str : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT_DEFAULT(str, object, PyUnicode_Check)
|
||||
str(const char *s) : object(PyUnicode_FromString(s), false) { }
|
||||
operator const char *() const {
|
||||
str(const std::string &s) : object(PyUnicode_FromStringAndSize(s.c_str(), s.length()), false) { }
|
||||
|
||||
operator std::string() const {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return PyUnicode_AsUTF8(m_ptr);
|
||||
#else
|
||||
m_temp = object(PyUnicode_AsUTF8String(m_ptr), false);
|
||||
if (m_temp.ptr() == nullptr)
|
||||
return nullptr;
|
||||
return PyString_AsString(m_temp.ptr());
|
||||
object temp(PyUnicode_AsUTF8String(m_ptr), false);
|
||||
if (temp.ptr() == nullptr)
|
||||
throw std::runtime_error("Unable to extract string contents!");
|
||||
return PyString_AsString(temp.ptr());
|
||||
#endif
|
||||
}
|
||||
private:
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
mutable object m_temp;
|
||||
#endif
|
||||
};
|
||||
|
||||
inline pybind11::str handle::str() const {
|
||||
@ -292,6 +265,23 @@ inline pybind11::str handle::str() const {
|
||||
return pybind11::str(str, false);
|
||||
}
|
||||
|
||||
class bytes : public object {
|
||||
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) { }
|
||||
|
||||
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!");
|
||||
return std::string(buffer, length);
|
||||
}
|
||||
};
|
||||
|
||||
class bool_ : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT_DEFAULT(bool_, object, PyBool_Check)
|
||||
@ -301,7 +291,7 @@ public:
|
||||
|
||||
class int_ : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT_DEFAULT(int_, object, detail::PyLong_Check_)
|
||||
PYBIND11_OBJECT_DEFAULT(int_, object, PYBIND11_LONG_CHECK)
|
||||
template <typename T,
|
||||
typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
|
||||
int_(T value) {
|
||||
@ -328,9 +318,9 @@ public:
|
||||
return (T) PyLong_AsUnsignedLong(m_ptr);
|
||||
} else {
|
||||
if (std::is_signed<T>::value)
|
||||
return (T) detail::PyLong_AsLongLong_(m_ptr);
|
||||
return (T) PYBIND11_LONG_AS_LONGLONG(m_ptr);
|
||||
else
|
||||
return (T) detail::PyLong_AsUnsignedLongLong_(m_ptr);
|
||||
return (T) PYBIND11_LONG_AS_UNSIGNED_LONGLONG(m_ptr);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -352,13 +342,8 @@ public:
|
||||
m_ptr = PySlice_New(start.ptr(), stop.ptr(), step.ptr());
|
||||
}
|
||||
bool compute(ssize_t length, ssize_t *start, ssize_t *stop, ssize_t *step, ssize_t *slicelength) const {
|
||||
return PySlice_GetIndicesEx(
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
m_ptr,
|
||||
#else
|
||||
(PySliceObject *) m_ptr,
|
||||
#endif
|
||||
length, start, stop, step, slicelength) == 0;
|
||||
return PySlice_GetIndicesEx((PYBIND11_SLICE_OBJECT *) m_ptr, length,
|
||||
start, stop, step, slicelength) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
@ -377,7 +362,7 @@ public:
|
||||
class tuple : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT(tuple, object, PyTuple_Check)
|
||||
tuple(size_t size = 0) : object(PyTuple_New((Py_ssize_t) size), false) { }
|
||||
tuple(size_t size = 0) : object(PyTuple_New((ssize_t) size), false) { }
|
||||
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); }
|
||||
};
|
||||
@ -466,11 +451,11 @@ inline std::string error_string() {
|
||||
return "";
|
||||
|
||||
if (tstate->curexc_type) {
|
||||
errorString += (const char *) handle(tstate->curexc_type).str();
|
||||
errorString += (std::string) handle(tstate->curexc_type).str();
|
||||
errorString += ": ";
|
||||
}
|
||||
if (tstate->curexc_value)
|
||||
errorString += (const char *) handle(tstate->curexc_value).str();
|
||||
errorString += (std::string) handle(tstate->curexc_value).str();
|
||||
|
||||
return errorString;
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ public:
|
||||
|
||||
NAMESPACE_END(detail)
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &os, const object &obj) { os << (const char *) obj.str(); return os; }
|
||||
inline std::ostream &operator<<(std::ostream &os, const object &obj) { os << (std::string) obj.str(); return os; }
|
||||
|
||||
NAMESPACE_END(pybind11)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user