enable *args and **kwargs notation (closes #190)

This commit is contained in:
Wenzel Jakob 2016-05-08 14:34:09 +02:00
parent e611823e4c
commit 6c03beb867
8 changed files with 57 additions and 11 deletions

View File

@ -19,6 +19,13 @@ void kw_func4(const std::vector<int> &entries) {
std::cout << endl;
}
void call_kw_func(py::function f) {
py::tuple args = py::make_tuple(1234);
py::dict kwargs;
kwargs["y"] = py::cast(5678);
f(*args, **kwargs);
}
void init_ex11(py::module &m) {
m.def("kw_func", &kw_func, py::arg("x"), py::arg("y"));
m.def("kw_func2", &kw_func, py::arg("x") = 100, py::arg("y") = 200);
@ -30,4 +37,5 @@ void init_ex11(py::module &m) {
list.push_back(17);
m.def("kw_func4", &kw_func4, py::arg("myList") = list);
m.def("call_kw_func", &call_kw_func);
}

View File

@ -5,7 +5,7 @@ import pydoc
sys.path.append('.')
from example import kw_func, kw_func2, kw_func3, kw_func4
from example import kw_func, kw_func2, kw_func3, kw_func4, call_kw_func
print(pydoc.render_doc(kw_func, "Help on %s"))
print(pydoc.render_doc(kw_func2, "Help on %s"))
@ -33,3 +33,5 @@ except Exception as e:
kw_func4()
kw_func4(myList = [1, 2, 3])
call_kw_func(kw_func2)

View File

@ -43,12 +43,12 @@ void dog_bark(const Dog &dog) {
}
bool test_callback1(py::object func) {
func.call();
func();
return false;
}
int test_callback2(py::object func) {
py::object result = func.call("Hello", 'x', true, 5);
py::object result = func("Hello", 'x', true, 5);
return result.cast<int>();
}

View File

@ -796,7 +796,7 @@ template <return_value_policy policy = return_value_policy::automatic_reference,
return result;
}
template <typename... Args> object handle::call(Args&&... args) const {
template <typename... Args> object handle::operator()(Args&&... args) const {
tuple args_tuple = pybind11::make_tuple(std::forward<Args>(args)...);
object result(PyObject_CallObject(m_ptr, args_tuple.ptr()), false);
if (!result)
@ -804,6 +804,24 @@ template <typename... Args> object handle::call(Args&&... args) const {
return result;
}
template <typename... Args> object handle::call(Args &&... args) const {
return operator()(std::forward<Args>(args)...);
}
inline object handle::operator()(detail::args args) const {
object result(PyObject_CallObject(m_ptr, args.ptr()), false);
if (!result)
throw error_already_set();
return result;
}
inline object handle::operator()(detail::args args, detail::kwargs kwargs) const {
object result(PyObject_Call(m_ptr, args.ptr(), kwargs.ptr()), false);
if (!result)
throw error_already_set();
return result;
}
#define PYBIND11_MAKE_OPAQUE(Type) \
namespace pybind11 { namespace detail { \
template<> class type_caster<Type> : public type_caster_base<Type> { }; \

View File

@ -145,7 +145,7 @@ struct type_caster<Type, typename std::enable_if<is_eigen_sparse<Type>::value>::
if (obj.get_type() != matrix_type.ptr()) {
try {
obj = matrix_type.call(obj);
obj = matrix_type(obj);
} catch (const error_already_set &) {
PyErr_Clear();
return false;
@ -233,7 +233,7 @@ struct type_caster<Type, typename std::enable_if<is_eigen_sparse<Type>::value>::
{ sizeof(StorageIndex) }
));
return matrix_type.call(
return matrix_type(
std::make_tuple(data, innerIndices, outerIndices),
std::make_pair(src.rows(), src.cols())
).release();

View File

@ -26,7 +26,7 @@ public:
object src(src_, true);
value = [src](Args... args) -> Return {
gil_scoped_acquire acq;
object retval(src.call(std::move(args)...));
object retval(src(std::move(args)...));
/* Visual studio 2015 parser issue: need parentheses around this expression */
return (retval.template cast<Return>());
};

View File

@ -176,7 +176,7 @@ protected:
if (a.descr)
a.descr = strdup(a.descr);
else if (a.value)
a.descr = strdup(((std::string) ((object) handle(a.value).attr("__repr__")).call().str()).c_str());
a.descr = strdup(((std::string) ((object) handle(a.value).attr("__repr__"))().str()).c_str());
}
auto const &registered_types = detail::get_internals().registered_types_cpp;
@ -1202,7 +1202,7 @@ inline function get_overload(const void *this_ptr, const char *name) {
pybind11::gil_scoped_acquire gil; \
pybind11::function overload = pybind11::get_overload(this, #name); \
if (overload) \
return overload.call(__VA_ARGS__).template cast<ret_type>(); }
return overload(__VA_ARGS__).template cast<ret_type>(); }
#define PYBIND11_OVERLOAD(ret_type, class_name, name, ...) \
PYBIND11_OVERLOAD_INT(ret_type, class_name, name, __VA_ARGS__) \

View File

@ -21,7 +21,7 @@ class str;
class object;
class dict;
class iterator;
namespace detail { class accessor; }
namespace detail { class accessor; class args; class kwargs; }
/// Holds a reference to a Python object (no reference counting)
class handle {
@ -43,11 +43,17 @@ public:
inline detail::accessor attr(const char *key) const;
inline pybind11::str str() const;
template <typename T> T cast() const;
template <typename ... Args> object call(Args&&... args_) const;
template <typename ... Args>
[[deprecated("call(...) was deprecated in favor of operator()(...)")]]
object call(Args&&... args) const;
template <typename ... Args> object operator()(Args&&... args) const;
inline object operator()(detail::args args) const;
inline object operator()(detail::args args, detail::kwargs kwargs) const;
operator bool() const { return m_ptr != nullptr; }
bool operator==(const handle &h) const { return m_ptr == h.m_ptr; }
bool operator!=(const handle &h) const { return m_ptr != h.m_ptr; }
bool check() const { return m_ptr != nullptr; }
inline detail::args operator*() const;
protected:
PyObject *m_ptr;
};
@ -212,6 +218,17 @@ private:
ssize_t pos = 0;
};
class kwargs : public handle {
public:
kwargs(handle h) : handle(h) { }
};
class args : public handle {
public:
args(handle h) : handle(h) { }
kwargs operator*() const { return kwargs(*this); }
};
inline bool PyIterable_Check(PyObject *obj) {
PyObject *iter = PyObject_GetIter(obj);
if (iter) {
@ -315,6 +332,7 @@ inline detail::accessor handle::attr(handle key) const { return detail::accessor
inline detail::accessor handle::attr(const char *key) const { return detail::accessor(ptr(), key, true); }
inline iterator handle::begin() const { return iterator(PyObject_GetIter(ptr()), false); }
inline iterator handle::end() const { return iterator(nullptr, false); }
inline detail::args handle::operator*() const { return detail::args(*this); }
class str : public object {
public: