Better NumPy support
diff --git a/include/pybind/cast.h b/include/pybind/cast.h
index 63ed19c..a3143d2 100644
--- a/include/pybind/cast.h
+++ b/include/pybind/cast.h
@@ -206,6 +206,22 @@
TYPE_CASTER(std::string, "str");
};
+#ifdef HAVE_WCHAR_H
+template <> class type_caster<std::wstring> {
+public:
+ bool load(PyObject *src, bool) {
+ const wchar_t *ptr = PyUnicode_AsWideCharString(src, nullptr);
+ if (!ptr) { PyErr_Clear(); return false; }
+ value = std::wstring(ptr);
+ return true;
+ }
+ static PyObject *cast(const std::wstring &src, return_value_policy /* policy */, PyObject * /* parent */) {
+ return PyUnicode_FromWideChar(src.c_str(), src.length());
+ }
+ TYPE_CASTER(std::wstring, "wstr");
+};
+#endif
+
template <> class type_caster<char> {
public:
bool load(PyObject *src, bool) {
@@ -474,6 +490,7 @@
TYPE_CASTER_PYTYPE(slice)
TYPE_CASTER_PYTYPE(tuple)
TYPE_CASTER_PYTYPE(function)
+TYPE_CASTER_PYTYPE(array)
#undef TYPE_CASTER
#undef TYPE_CASTER_PYTYPE
diff --git a/include/pybind/pybind.h b/include/pybind/pybind.h
index 9f28561..d4ebdc8 100644
--- a/include/pybind/pybind.h
+++ b/include/pybind/pybind.h
@@ -132,7 +132,10 @@
entry = backup;
}
std::string signatures;
+ int it = 0;
while (entry) { /* Create pydoc entry */
+ if (sibling.ptr())
+ signatures += std::to_string(++it) + ". ";
signatures += "Signature : " + std::string(entry->signature) + "\n";
if (!entry->doc.empty())
signatures += "\n" + std::string(entry->doc) + "\n";
diff --git a/include/pybind/pytypes.h b/include/pybind/pytypes.h
index db612b5..33aa69f 100644
--- a/include/pybind/pytypes.h
+++ b/include/pybind/pytypes.h
@@ -322,6 +322,88 @@
Py_buffer *view = nullptr;
};
+class array : public buffer {
+protected:
+ struct API {
+ enum Entries {
+ API_PyArray_Type = 2,
+ API_PyArray_DescrFromType = 45,
+ API_PyArray_NewCopy = 85,
+ API_PyArray_NewFromDescr = 94
+ };
+
+ static API lookup() {
+ PyObject *numpy = PyImport_ImportModule("numpy.core.multiarray");
+ PyObject *capsule = numpy ? PyObject_GetAttrString(numpy, "_ARRAY_API") : nullptr;
+ void **api_ptr = (void **) (capsule ? PyCapsule_GetPointer(capsule, NULL) : nullptr);
+ Py_XDECREF(capsule);
+ Py_XDECREF(numpy);
+ if (api_ptr == nullptr)
+ throw std::runtime_error("Could not acquire pointer to NumPy API!");
+ API api;
+ api.PyArray_DescrFromType = (decltype(api.PyArray_DescrFromType)) api_ptr[API_PyArray_DescrFromType];
+ api.PyArray_NewFromDescr = (decltype(api.PyArray_NewFromDescr)) api_ptr[API_PyArray_NewFromDescr];
+ api.PyArray_NewCopy = (decltype(api.PyArray_NewCopy)) api_ptr[API_PyArray_NewCopy];
+ api.PyArray_Type = (decltype(api.PyArray_Type)) api_ptr[API_PyArray_Type];
+ return api;
+ }
+
+ bool PyArray_Check(PyObject *obj) const {
+ return (bool) PyObject_TypeCheck(obj, PyArray_Type);
+ }
+
+ PyObject *(*PyArray_DescrFromType)(int);
+ PyObject *(*PyArray_NewFromDescr)
+ (PyTypeObject *, PyObject *, int, Py_intptr_t *,
+ Py_intptr_t *, void *, int, PyObject *);
+ PyObject *(*PyArray_NewCopy)(PyObject *, int);
+ PyTypeObject *PyArray_Type;
+ };
+public:
+ PYTHON_OBJECT_DEFAULT(array, buffer, lookup_api().PyArray_Check)
+
+ template <typename Type> array(size_t size, const Type *ptr) {
+ API& api = lookup_api();
+ PyObject *descr = api.PyArray_DescrFromType(
+ (int) format_descriptor<Type>::value()[0]);
+ if (descr == nullptr)
+ throw std::runtime_error("NumPy: unsupported buffer format!");
+ Py_intptr_t shape = (Py_intptr_t) size;
+ PyObject *tmp = api.PyArray_NewFromDescr(
+ api.PyArray_Type, descr, 1, &shape, nullptr, (void *) ptr, 0, nullptr);
+ if (tmp == nullptr)
+ throw std::runtime_error("NumPy: unable to create array!");
+ m_ptr = api.PyArray_NewCopy(tmp, -1 /* any order */);
+ Py_DECREF(tmp);
+ if (m_ptr == nullptr)
+ throw std::runtime_error("NumPy: unable to copy array!");
+ }
+
+ array(const buffer_info &info) {
+ API& api = lookup_api();
+ if (info.format.size() != 1)
+ throw std::runtime_error("Unsupported buffer format!");
+ PyObject *descr = api.PyArray_DescrFromType(info.format[0]);
+ if (descr == nullptr)
+ throw std::runtime_error("NumPy: unsupported buffer format '" + info.format + "'!");
+ PyObject *tmp = api.PyArray_NewFromDescr(
+ api.PyArray_Type, descr, info.ndim, (Py_intptr_t *) &info.shape[0],
+ (Py_intptr_t *) &info.strides[0], info.ptr, 0, nullptr);
+ if (tmp == nullptr)
+ throw std::runtime_error("NumPy: unable to create array!");
+ m_ptr = api.PyArray_NewCopy(tmp, -1 /* any order */);
+ Py_DECREF(tmp);
+ if (m_ptr == nullptr)
+ throw std::runtime_error("NumPy: unable to copy array!");
+ }
+protected:
+ static API &lookup_api() {
+ static API api = API::lookup();
+ return api;
+ }
+};
+
+
NAMESPACE_BEGIN(detail)
inline internals &get_internals() {
static internals *internals_ptr = nullptr;