mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 06:35:12 +00:00
nicer code separation, cleanup logic, std::function type caster
This commit is contained in:
parent
a576e6a8ca
commit
281aa0e668
@ -22,7 +22,10 @@ find_package(PythonInterp 3 REQUIRED)
|
||||
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE)
|
||||
if (UNIX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-unsequenced")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unsequenced")
|
||||
endif()
|
||||
if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -flto")
|
||||
endif()
|
||||
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#include "example.h"
|
||||
#include <pybind/stl.h>
|
||||
|
||||
class Example2 {
|
||||
public:
|
||||
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#include "example.h"
|
||||
#include <pybind/functional.h>
|
||||
|
||||
|
||||
class Pet {
|
||||
@ -73,6 +74,14 @@ void test_callback3(Example5 *ex, int value) {
|
||||
ex->callback(value);
|
||||
}
|
||||
|
||||
void test_callback4(const std::function<int(int)> &func) {
|
||||
cout << "func(43) = " << func(43)<< std::endl;
|
||||
}
|
||||
|
||||
std::function<int(int)> test_callback5() {
|
||||
return [](int i) { return i+1; };
|
||||
}
|
||||
|
||||
void init_ex5(py::module &m) {
|
||||
py::class_<Pet> pet_class(m, "Pet");
|
||||
pet_class
|
||||
@ -89,6 +98,8 @@ void init_ex5(py::module &m) {
|
||||
m.def("test_callback1", &test_callback1);
|
||||
m.def("test_callback2", &test_callback2);
|
||||
m.def("test_callback3", &test_callback3);
|
||||
m.def("test_callback4", &test_callback4);
|
||||
m.def("test_callback5", &test_callback5);
|
||||
|
||||
py::class_<Example5>(m, "Example5")
|
||||
.def(py::init<py::object, int>());
|
||||
|
@ -22,6 +22,8 @@ except Exception as e:
|
||||
from example import test_callback1
|
||||
from example import test_callback2
|
||||
from example import test_callback3
|
||||
from example import test_callback4
|
||||
from example import test_callback5
|
||||
from example import Example5
|
||||
|
||||
def func1():
|
||||
@ -43,3 +45,7 @@ print(test_callback2(func2))
|
||||
|
||||
callback = MyCallback(3)
|
||||
test_callback3(callback, 4)
|
||||
|
||||
test_callback4(lambda i: i+1)
|
||||
f = test_callback5()
|
||||
print("func(43) = %i" % f(43))
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
#include <pybind/pytypes.h>
|
||||
#include <pybind/typeid.h>
|
||||
#include <map>
|
||||
#include <array>
|
||||
|
||||
NAMESPACE_BEGIN(pybind)
|
||||
@ -167,14 +166,14 @@ PYBIND_TYPE_CASTER_NUMBER(size_t, size_t, PyLong_AsSize_t, PyLong_FromSize_t)
|
||||
PYBIND_TYPE_CASTER_NUMBER(float, float, PyFloat_AsDouble, PyFloat_FromDouble)
|
||||
PYBIND_TYPE_CASTER_NUMBER(double, double, PyFloat_AsDouble, PyFloat_FromDouble)
|
||||
|
||||
template <> class type_caster<detail::void_type> {
|
||||
template <> class type_caster<void_type> {
|
||||
public:
|
||||
bool load(PyObject *, bool) { return true; }
|
||||
static PyObject *cast(detail::void_type, return_value_policy /* policy */, PyObject * /* parent */) {
|
||||
static PyObject *cast(void_type, return_value_policy /* policy */, PyObject * /* parent */) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
PYBIND_TYPE_CASTER(detail::void_type, "None");
|
||||
PYBIND_TYPE_CASTER(void_type, "None");
|
||||
};
|
||||
|
||||
template <> class type_caster<bool> {
|
||||
@ -192,23 +191,6 @@ public:
|
||||
PYBIND_TYPE_CASTER(bool, "bool");
|
||||
};
|
||||
|
||||
template <typename T> class type_caster<std::complex<T>> {
|
||||
public:
|
||||
bool load(PyObject *src, bool) {
|
||||
Py_complex result = PyComplex_AsCComplex(src);
|
||||
if (result.real == -1.0 && PyErr_Occurred()) {
|
||||
PyErr_Clear();
|
||||
return false;
|
||||
}
|
||||
value = std::complex<T>((T) result.real, (T) result.imag);
|
||||
return true;
|
||||
}
|
||||
static PyObject *cast(const std::complex<T> &src, return_value_policy /* policy */, PyObject * /* parent */) {
|
||||
return PyComplex_FromDoubles((double) src.real(), (double) src.imag());
|
||||
}
|
||||
PYBIND_TYPE_CASTER(std::complex<T>, "complex");
|
||||
};
|
||||
|
||||
template <> class type_caster<std::string> {
|
||||
public:
|
||||
bool load(PyObject *src, bool) {
|
||||
@ -265,83 +247,6 @@ protected:
|
||||
char *value;
|
||||
};
|
||||
|
||||
template <typename Value> struct type_caster<std::vector<Value>> {
|
||||
typedef std::vector<Value> type;
|
||||
typedef type_caster<Value> value_conv;
|
||||
public:
|
||||
bool load(PyObject *src, bool convert) {
|
||||
if (!PyList_Check(src))
|
||||
return false;
|
||||
size_t size = (size_t) PyList_GET_SIZE(src);
|
||||
value.reserve(size);
|
||||
value.clear();
|
||||
for (size_t i=0; i<size; ++i) {
|
||||
value_conv conv;
|
||||
if (!conv.load(PyList_GetItem(src, (ssize_t) i), convert))
|
||||
return false;
|
||||
value.push_back((Value) conv);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
|
||||
PyObject *list = PyList_New(src.size());
|
||||
size_t index = 0;
|
||||
for (auto const &value: src) {
|
||||
PyObject *value_ = value_conv::cast(value, policy, parent);
|
||||
if (!value_) {
|
||||
Py_DECREF(list);
|
||||
return nullptr;
|
||||
}
|
||||
PyList_SetItem(list, index++, value_);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
PYBIND_TYPE_CASTER(type, "list<" + value_conv::name() + ">");
|
||||
};
|
||||
|
||||
template <typename Key, typename Value> struct type_caster<std::map<Key, Value>> {
|
||||
public:
|
||||
typedef std::map<Key, Value> type;
|
||||
typedef type_caster<Key> key_conv;
|
||||
typedef type_caster<Value> value_conv;
|
||||
|
||||
bool load(PyObject *src, bool convert) {
|
||||
if (!PyDict_Check(src))
|
||||
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))
|
||||
return false;
|
||||
value[kconv] = vconv;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
|
||||
PyObject *dict = PyDict_New();
|
||||
for (auto const &kv: src) {
|
||||
PyObject *key = key_conv::cast(kv.first, policy, parent);
|
||||
PyObject *value = value_conv::cast(kv.second, policy, parent);
|
||||
if (!key || !value || PyDict_SetItem(dict, key, value) < 0) {
|
||||
Py_XDECREF(key);
|
||||
Py_XDECREF(value);
|
||||
Py_DECREF(dict);
|
||||
return nullptr;
|
||||
}
|
||||
Py_DECREF(key);
|
||||
Py_DECREF(value);
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
PYBIND_TYPE_CASTER(type, "dict<" + key_conv::name() + ", " + value_conv::name() + ">");
|
||||
};
|
||||
|
||||
template <typename T1, typename T2> class type_caster<std::pair<T1, T2>> {
|
||||
typedef std::pair<T1, T2> type;
|
||||
public:
|
||||
@ -354,8 +259,8 @@ public:
|
||||
}
|
||||
|
||||
static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
|
||||
PyObject *o1 = type_caster<typename detail::decay<T1>::type>::cast(src.first, policy, parent);
|
||||
PyObject *o2 = type_caster<typename detail::decay<T2>::type>::cast(src.second, policy, parent);
|
||||
PyObject *o1 = type_caster<typename decay<T1>::type>::cast(src.first, policy, parent);
|
||||
PyObject *o2 = type_caster<typename decay<T2>::type>::cast(src.second, policy, parent);
|
||||
if (!o1 || !o2) {
|
||||
Py_XDECREF(o1);
|
||||
Py_XDECREF(o2);
|
||||
@ -375,11 +280,11 @@ public:
|
||||
return type(first, second);
|
||||
}
|
||||
protected:
|
||||
type_caster<typename detail::decay<T1>::type> first;
|
||||
type_caster<typename detail::decay<T2>::type> second;
|
||||
type_caster<typename decay<T1>::type> first;
|
||||
type_caster<typename decay<T2>::type> second;
|
||||
};
|
||||
|
||||
template <typename ... Tuple> class type_caster<std::tuple<Tuple...>> {
|
||||
template <typename... Tuple> class type_caster<std::tuple<Tuple...>> {
|
||||
typedef std::tuple<Tuple...> type;
|
||||
public:
|
||||
enum { size = sizeof...(Tuple) };
|
||||
@ -394,7 +299,7 @@ public:
|
||||
|
||||
static std::string name(const char **keywords = nullptr, const char **values = nullptr) {
|
||||
std::array<std::string, size> names {{
|
||||
type_caster<typename detail::decay<Tuple>::type>::name()...
|
||||
type_caster<typename decay<Tuple>::type>::name()...
|
||||
}};
|
||||
std::string result("(");
|
||||
int counter = 0;
|
||||
@ -419,9 +324,9 @@ public:
|
||||
return call<ReturnValue>(std::forward<Func>(f), typename make_index_sequence<sizeof...(Tuple)>::type());
|
||||
}
|
||||
|
||||
template <typename ReturnValue, typename Func> typename std::enable_if<std::is_void<ReturnValue>::value, detail::void_type>::type call(Func &&f) {
|
||||
template <typename ReturnValue, typename Func> typename std::enable_if<std::is_void<ReturnValue>::value, void_type>::type call(Func &&f) {
|
||||
call<ReturnValue>(std::forward<Func>(f), typename make_index_sequence<sizeof...(Tuple)>::type());
|
||||
return detail::void_type();
|
||||
return void_type();
|
||||
}
|
||||
|
||||
operator type() {
|
||||
@ -443,8 +348,9 @@ protected:
|
||||
if (PyTuple_Size(src) != size)
|
||||
return false;
|
||||
std::array<bool, size> results {{
|
||||
std::get<Indices>(value).load(PyTuple_GetItem(src, Indices), convert)...
|
||||
(PyTuple_GET_ITEM(src, Indices) != nullptr ? std::get<Indices>(value).load(PyTuple_GET_ITEM(src, Indices), convert) : false)...
|
||||
}};
|
||||
(void) convert; /* avoid a warning when the tuple is empty */
|
||||
for (bool r : results)
|
||||
if (!r)
|
||||
return false;
|
||||
@ -454,7 +360,7 @@ protected:
|
||||
/* Implementation: Convert a C++ tuple into a Python tuple */
|
||||
template <size_t ... Indices> static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent, index_sequence<Indices...>) {
|
||||
std::array<PyObject *, size> results {{
|
||||
type_caster<typename detail::decay<Tuple>::type>::cast(std::get<Indices>(src), policy, parent)...
|
||||
type_caster<typename decay<Tuple>::type>::cast(std::get<Indices>(src), policy, parent)...
|
||||
}};
|
||||
bool success = true;
|
||||
for (auto result : results)
|
||||
@ -475,7 +381,7 @@ protected:
|
||||
}
|
||||
|
||||
protected:
|
||||
std::tuple<type_caster<typename detail::decay<Tuple>::type>...> value;
|
||||
std::tuple<type_caster<typename decay<Tuple>::type>...> value;
|
||||
};
|
||||
|
||||
/// Type caster for holder types like std::shared_ptr, etc.
|
||||
@ -542,7 +448,7 @@ template <typename T> inline object cast(const T &value, return_value_policy pol
|
||||
|
||||
template <typename T> inline T handle::cast() { return pybind::cast<T>(m_ptr); }
|
||||
|
||||
template <typename ... Args> inline object handle::call(Args&&... args_) {
|
||||
template <typename... Args> inline object handle::call(Args&&... args_) {
|
||||
const size_t size = sizeof...(Args);
|
||||
std::array<PyObject *, size> args{
|
||||
{ detail::type_caster<typename detail::decay<Args>::type>::cast(
|
||||
|
@ -31,9 +31,7 @@
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <complex>
|
||||
|
||||
/// Include Python header, disable linking to pythonX_d.lib on Windows in debug mode
|
||||
#if defined(_MSC_VER)
|
||||
@ -46,6 +44,15 @@
|
||||
#endif
|
||||
#endif
|
||||
#include <Python.h>
|
||||
#ifdef isalnum
|
||||
#undef isalnum
|
||||
#undef isalpha
|
||||
#undef islower
|
||||
#undef isspace
|
||||
#undef isupper
|
||||
#undef tolower
|
||||
#undef toupper
|
||||
#endif
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_DEBUG_MARKER)
|
||||
#define _DEBUG
|
||||
@ -79,12 +86,10 @@ enum class return_value_policy : int {
|
||||
|
||||
/// Format strings for basic number types
|
||||
template <typename type> struct format_descriptor { };
|
||||
#define DECL_FMT(t, n) template<> struct format_descriptor<t> { static std::string value() { return n; }; };
|
||||
DECL_FMT(int8_t, "b"); DECL_FMT(uint8_t, "B"); DECL_FMT(int16_t, "h"); DECL_FMT(uint16_t, "H");
|
||||
DECL_FMT(int32_t, "i"); DECL_FMT(uint32_t, "I"); DECL_FMT(int64_t, "q"); DECL_FMT(uint64_t, "Q");
|
||||
DECL_FMT(float, "f"); DECL_FMT(double, "d"); DECL_FMT(bool, "?");
|
||||
DECL_FMT(std::complex<float>, "Zf"); DECL_FMT(std::complex<double>, "Zd");
|
||||
#undef DECL_FMT
|
||||
#define PYBIND_DECL_FMT(t, n) template<> struct format_descriptor<t> { static std::string value() { return n; }; };
|
||||
PYBIND_DECL_FMT(int8_t, "b"); PYBIND_DECL_FMT(uint8_t, "B"); PYBIND_DECL_FMT(int16_t, "h"); PYBIND_DECL_FMT(uint16_t, "H");
|
||||
PYBIND_DECL_FMT(int32_t, "i"); PYBIND_DECL_FMT(uint32_t, "I"); PYBIND_DECL_FMT(int64_t, "q"); PYBIND_DECL_FMT(uint64_t, "Q");
|
||||
PYBIND_DECL_FMT(float, "f"); PYBIND_DECL_FMT(double, "d"); PYBIND_DECL_FMT(bool, "?");
|
||||
|
||||
/// Information record describing a Python buffer object
|
||||
struct buffer_info {
|
||||
@ -162,5 +167,6 @@ template <typename T, size_t N> struct decay<T[N]> { typedef typename deca
|
||||
|
||||
/// Helper type to replace 'void' in some expressions
|
||||
struct void_type { };
|
||||
|
||||
NAMESPACE_END(detail)
|
||||
NAMESPACE_END(pybind)
|
||||
|
40
include/pybind/complex.h
Normal file
40
include/pybind/complex.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
pybind/complex.h: Complex number support
|
||||
|
||||
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
|
||||
|
||||
All rights reserved. Use of this source code is governed by a
|
||||
BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <pybind/pybind.h>
|
||||
#include <complex>
|
||||
|
||||
NAMESPACE_BEGIN(pybind)
|
||||
|
||||
PYBIND_DECL_FMT(std::complex<float>, "Zf");
|
||||
PYBIND_DECL_FMT(std::complex<double>, "Zd");
|
||||
|
||||
NAMESPACE_BEGIN(detail)
|
||||
template <typename T> class type_caster<std::complex<T>> {
|
||||
public:
|
||||
bool load(PyObject *src, bool) {
|
||||
Py_complex result = PyComplex_AsCComplex(src);
|
||||
if (result.real == -1.0 && PyErr_Occurred()) {
|
||||
PyErr_Clear();
|
||||
return false;
|
||||
}
|
||||
value = std::complex<T>((T) result.real, (T) result.imag);
|
||||
return true;
|
||||
}
|
||||
|
||||
static PyObject *cast(const std::complex<T> &src, return_value_policy /* policy */, PyObject * /* parent */) {
|
||||
return PyComplex_FromDoubles((double) src.real(), (double) src.imag());
|
||||
}
|
||||
|
||||
PYBIND_TYPE_CASTER(std::complex<T>, "complex");
|
||||
};
|
||||
NAMESPACE_END(detail)
|
||||
NAMESPACE_END(pybind)
|
45
include/pybind/functional.h
Normal file
45
include/pybind/functional.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
pybind/functional.h: std::function<> support
|
||||
|
||||
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
|
||||
|
||||
All rights reserved. Use of this source code is governed by a
|
||||
BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <pybind/pybind.h>
|
||||
#include <functional>
|
||||
|
||||
NAMESPACE_BEGIN(pybind)
|
||||
NAMESPACE_BEGIN(detail)
|
||||
|
||||
template <typename Return, typename... Args> struct type_caster<std::function<Return(Args...)>> {
|
||||
typedef std::function<Return(Args...)> type;
|
||||
public:
|
||||
|
||||
bool load(PyObject *src_, bool) {
|
||||
if (!PyFunction_Check(src_))
|
||||
return false;
|
||||
object src(src_, true);
|
||||
value = [src](Args... args) -> Return {
|
||||
object retval(pybind::handle(src).call<Args...>(std::move(args)...));
|
||||
/* Visual studio 2015 parser issue: need parentheses around this expression */
|
||||
return (retval.template cast<Return>());
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Func>
|
||||
static PyObject *cast(Func &&f_, return_value_policy policy, PyObject *) {
|
||||
cpp_function f(std::forward<Func>(f_), policy);
|
||||
f.inc_ref();
|
||||
return f.ptr();
|
||||
}
|
||||
|
||||
PYBIND_TYPE_CASTER(type, "function<" + type_caster<std::tuple<Args...>>::name() + " -> " + type_caster<typename decay<Return>::type>::name() + ">");
|
||||
};
|
||||
|
||||
NAMESPACE_END(detail)
|
||||
NAMESPACE_END(pybind)
|
@ -10,7 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <pybind/pybind.h>
|
||||
#include <functional>
|
||||
#include <pybind/complex.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
@ -126,6 +126,8 @@ public:
|
||||
array_dtype() : array() { }
|
||||
static bool is_non_null(PyObject *ptr) { return ptr != nullptr; }
|
||||
PyObject *ensure(PyObject *ptr) {
|
||||
if (ptr == nullptr)
|
||||
return nullptr;
|
||||
API &api = lookup_api();
|
||||
PyObject *descr = api.PyArray_DescrFromType(npy_format_descriptor<T>::value);
|
||||
return api.PyArray_FromAny(ptr, descr, 0, 0,
|
||||
@ -158,7 +160,8 @@ template <typename Func, typename Return, typename... Args>
|
||||
struct vectorize_helper {
|
||||
typename std::remove_reference<Func>::type f;
|
||||
|
||||
vectorize_helper(const Func &f) : f(f) { }
|
||||
template <typename T>
|
||||
vectorize_helper(T&&f) : f(std::forward<T>(f)) { }
|
||||
|
||||
object operator()(array_dtype<Args>... args) {
|
||||
return run(args..., typename make_index_sequence<sizeof...(Args)>::type());
|
||||
|
@ -16,9 +16,15 @@
|
||||
#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: 4100) // warning C4100: Unreferenced formal parameter
|
||||
#pragma warning(disable: 4512) // warning C4512: Assignment operator was implicitly defined as deleted
|
||||
#elif defined(__GNUG__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
#endif
|
||||
|
||||
#include <pybind/cast.h>
|
||||
#include <iostream>
|
||||
|
||||
NAMESPACE_BEGIN(pybind)
|
||||
|
||||
@ -57,7 +63,8 @@ private:
|
||||
struct function_entry {
|
||||
const char *name = nullptr;
|
||||
PyObject * (*impl) (function_entry *, PyObject *, PyObject *, PyObject *);
|
||||
void *data;
|
||||
PyMethodDef *def;
|
||||
void *data = nullptr;
|
||||
bool is_constructor = false, is_method = false;
|
||||
short keywords = 0;
|
||||
return_value_policy policy = return_value_policy::automatic;
|
||||
@ -304,6 +311,17 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
static void destruct(function_entry *entry) {
|
||||
while (entry) {
|
||||
delete entry->def;
|
||||
operator delete(entry->data);
|
||||
Py_XDECREF(entry->sibling);
|
||||
function_entry *next = entry->next;
|
||||
delete entry;
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
|
||||
void initialize(function_entry *entry, int args) {
|
||||
if (entry->name == nullptr)
|
||||
entry->name = "";
|
||||
@ -316,13 +334,13 @@ private:
|
||||
entry->is_constructor = !strcmp(entry->name, "__init__");
|
||||
|
||||
if (!entry->sibling || !PyCFunction_Check(entry->sibling)) {
|
||||
PyMethodDef *def = new PyMethodDef();
|
||||
memset(def, 0, sizeof(PyMethodDef));
|
||||
def->ml_name = entry->name;
|
||||
def->ml_meth = reinterpret_cast<PyCFunction>(*dispatcher);
|
||||
def->ml_flags = METH_VARARGS | METH_KEYWORDS;
|
||||
capsule entry_capsule(entry);
|
||||
m_ptr = PyCFunction_New(def, entry_capsule.ptr());
|
||||
entry->def = new PyMethodDef();
|
||||
memset(entry->def, 0, sizeof(PyMethodDef));
|
||||
entry->def->ml_name = entry->name;
|
||||
entry->def->ml_meth = reinterpret_cast<PyCFunction>(*dispatcher);
|
||||
entry->def->ml_flags = METH_VARARGS | METH_KEYWORDS;
|
||||
capsule entry_capsule(entry, [](PyObject *o) { destruct((function_entry *) PyCapsule_GetPointer(o, nullptr)); });
|
||||
m_ptr = PyCFunction_New(entry->def, entry_capsule.ptr());
|
||||
if (!m_ptr)
|
||||
throw std::runtime_error("cpp_function::cpp_function(): Could not allocate function object");
|
||||
} else {
|
||||
@ -335,6 +353,7 @@ private:
|
||||
parent->next = entry;
|
||||
entry = backup;
|
||||
}
|
||||
|
||||
std::string signatures;
|
||||
int index = 0;
|
||||
function_entry *it = entry;
|
||||
@ -799,4 +818,7 @@ NAMESPACE_END(pybind)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#elif defined(__GNUG__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
|
@ -217,7 +217,6 @@ public:
|
||||
};
|
||||
|
||||
inline pybind::str handle::str() const { return pybind::str(PyObject_Str(m_ptr), false); }
|
||||
inline std::ostream &operator<<(std::ostream &os, const object &obj) { os << (const char *) obj.str(); return os; }
|
||||
|
||||
class bool_ : public object {
|
||||
public:
|
||||
@ -258,7 +257,8 @@ public:
|
||||
class capsule : public object {
|
||||
public:
|
||||
PYBIND_OBJECT_DEFAULT(capsule, object, PyCapsule_CheckExact)
|
||||
capsule(void *value) : object(PyCapsule_New(value, nullptr, nullptr), false) { }
|
||||
capsule(PyObject *obj, bool borrowed) : object(obj, borrowed) { }
|
||||
capsule(void *value, void (*destruct)(PyObject *) = nullptr) : object(PyCapsule_New(value, nullptr, destruct), false) { }
|
||||
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!");
|
||||
|
109
include/pybind/stl.h
Normal file
109
include/pybind/stl.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
pybind/complex.h: Complex number support
|
||||
|
||||
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
|
||||
|
||||
All rights reserved. Use of this source code is governed by a
|
||||
BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <pybind/pybind.h>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(pybind)
|
||||
NAMESPACE_BEGIN(detail)
|
||||
|
||||
template <typename Value> struct type_caster<std::vector<Value>> {
|
||||
typedef std::vector<Value> type;
|
||||
typedef type_caster<Value> value_conv;
|
||||
public:
|
||||
bool load(PyObject *src, bool convert) {
|
||||
if (!PyList_Check(src))
|
||||
return false;
|
||||
size_t size = (size_t) PyList_GET_SIZE(src);
|
||||
value.reserve(size);
|
||||
value.clear();
|
||||
for (size_t i=0; i<size; ++i) {
|
||||
value_conv conv;
|
||||
if (!conv.load(PyList_GetItem(src, (ssize_t) i), convert))
|
||||
return false;
|
||||
value.push_back((Value) conv);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
|
||||
PyObject *list = PyList_New(src.size());
|
||||
size_t index = 0;
|
||||
for (auto const &value: src) {
|
||||
PyObject *value_ = value_conv::cast(value, policy, parent);
|
||||
if (!value_) {
|
||||
Py_DECREF(list);
|
||||
return nullptr;
|
||||
}
|
||||
PyList_SetItem(list, index++, value_);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
PYBIND_TYPE_CASTER(type, "list<" + value_conv::name() + ">");
|
||||
};
|
||||
|
||||
template <typename Key, typename Value> struct type_caster<std::map<Key, Value>> {
|
||||
public:
|
||||
typedef std::map<Key, Value> type;
|
||||
typedef type_caster<Key> key_conv;
|
||||
typedef type_caster<Value> value_conv;
|
||||
|
||||
bool load(PyObject *src, bool convert) {
|
||||
if (!PyDict_Check(src))
|
||||
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))
|
||||
return false;
|
||||
value[kconv] = vconv;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
|
||||
PyObject *dict = PyDict_New();
|
||||
for (auto const &kv: src) {
|
||||
PyObject *key = key_conv::cast(kv.first, policy, parent);
|
||||
PyObject *value = value_conv::cast(kv.second, policy, parent);
|
||||
if (!key || !value || PyDict_SetItem(dict, key, value) < 0) {
|
||||
Py_XDECREF(key);
|
||||
Py_XDECREF(value);
|
||||
Py_DECREF(dict);
|
||||
return nullptr;
|
||||
}
|
||||
Py_DECREF(key);
|
||||
Py_DECREF(value);
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
PYBIND_TYPE_CASTER(type, "dict<" + key_conv::name() + ", " + value_conv::name() + ">");
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &os, const object &obj) { os << (const char *) obj.str(); return os; }
|
||||
|
||||
NAMESPACE_END(detail)
|
||||
NAMESPACE_END(pybind)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
@ -212,7 +212,13 @@ if __name__ == '__main__':
|
||||
#define __DOC3(n1, n2, n3) __doc_##n1##_##n2##_##n3
|
||||
#define __DOC4(n1, n2, n3, n4) __doc_##n1##_##n2##_##n3##_##n4
|
||||
#define __DOC5(n1, n2, n3, n4, n5) __doc_##n1##_##n2##_##n3##_##n4_##n5
|
||||
#define DOC(...) __CAT2(__DOC, __VA_SIZE(__VA_ARGS__))(__VA_ARGS__)''')
|
||||
#define DOC(...) __CAT2(__DOC, __VA_SIZE(__VA_ARGS__))(__VA_ARGS__)
|
||||
|
||||
#if defined(__GNUG__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
#endif
|
||||
''')
|
||||
|
||||
output = []
|
||||
for filename in filenames:
|
||||
@ -226,3 +232,9 @@ if __name__ == '__main__':
|
||||
output.sort()
|
||||
for l in output:
|
||||
print(l)
|
||||
|
||||
print('''
|
||||
#if defined(__GNUG__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
''')
|
||||
|
Loading…
Reference in New Issue
Block a user