Skip to content

Commit a3dbdc6

Browse files
authored
Merge pull request #372 from dean0x7d/keywords
Keyword arguments and generalized unpacking for C++ API
2 parents 6f017cf + 60b2680 commit a3dbdc6

16 files changed

+575
-130
lines changed

docs/advanced.rst

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,24 +1622,76 @@ It is also possible to call python functions via ``operator()``.
16221622
py::object result_py = f(1234, "hello", some_instance);
16231623
MyClass &result = result_py.cast<MyClass>();
16241624
1625-
The special ``f(*args)`` and ``f(*args, **kwargs)`` syntax is also supported to
1626-
supply arbitrary argument and keyword lists, although these cannot be mixed
1627-
with other parameters.
1625+
Keyword arguments are also supported. In Python, there is the usual call syntax:
1626+
1627+
.. code-block:: python
1628+
1629+
def f(number, say, to):
1630+
... # function code
1631+
1632+
f(1234, say="hello", to=some_instance) # keyword call in Python
1633+
1634+
In C++, the same call can be made using:
16281635

16291636
.. code-block:: cpp
16301637
1631-
py::function f = <...>;
1638+
using pybind11::literals; // to bring in the `_a` literal
1639+
f(1234, "say"_a="hello", "to"_a=some_instance); // keyword call in C++
1640+
1641+
Unpacking of ``*args`` and ``**kwargs`` is also possible and can be mixed with
1642+
other arguments:
1643+
1644+
.. code-block:: cpp
1645+
1646+
// * unpacking
1647+
py::tuple args = py::make_tuple(1234, "hello", some_instance);
1648+
f(*args);
1649+
1650+
// ** unpacking
1651+
py::dict kwargs = py::dict("number"_a=1234, "say"_a="hello", "to"_a=some_instance);
1652+
f(**kwargs);
1653+
1654+
// mixed keywords, * and ** unpacking
16321655
py::tuple args = py::make_tuple(1234);
1633-
py::dict kwargs;
1634-
kwargs["y"] = py::cast(5678);
1635-
py::object result = f(*args, **kwargs);
1656+
py::dict kwargs = py::dict("to"_a=some_instance);
1657+
f(*args, "say"_a="hello", **kwargs);
1658+
1659+
Generalized unpacking according to PEP448_ is also supported:
1660+
1661+
.. code-block:: cpp
1662+
1663+
py::dict kwargs1 = py::dict("number"_a=1234);
1664+
py::dict kwargs2 = py::dict("to"_a=some_instance);
1665+
f(**kwargs1, "say"_a="hello", **kwargs2);
16361666
16371667
.. seealso::
16381668

16391669
The file :file:`tests/test_python_types.cpp` contains a complete
16401670
example that demonstrates passing native Python types in more detail. The
1641-
file :file:`tests/test_kwargs_and_defaults.cpp` discusses usage
1642-
of ``args`` and ``kwargs``.
1671+
file :file:`tests/test_callbacks.cpp` presents a few examples of calling
1672+
Python functions from C++, including keywords arguments and unpacking.
1673+
1674+
.. _PEP448: https://www.python.org/dev/peps/pep-0448/
1675+
1676+
Using Python's print function in C++
1677+
====================================
1678+
1679+
The usual way to write output in C++ is using ``std::cout`` while in Python one
1680+
would use ``print``. Since these methods use different buffers, mixing them can
1681+
lead to output order issues. To resolve this, pybind11 modules can use the
1682+
:func:`py::print` function which writes to Python's ``sys.stdout`` for consistency.
1683+
1684+
Python's ``print`` function is replicated in the C++ API including optional
1685+
keyword arguments ``sep``, ``end``, ``file``, ``flush``. Everything works as
1686+
expected in Python:
1687+
1688+
.. code-block:: cpp
1689+
1690+
py::print(1, 2.0, "three"); // 1 2.0 three
1691+
py::print(1, 2.0, "three", "sep"_a="-"); // 1-2.0-three
1692+
1693+
auto args = py::make_tuple("unpacked", true);
1694+
py::print("->", *args, "end"_a="<-"); // -> unpacked True <-
16431695
16441696
Default arguments revisited
16451697
===========================

docs/changelog.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ Breaking changes queued for v2.0.0 (Not yet released)
4646
* Added constructors for ``str`` and ``bytes`` from zero-terminated char pointers,
4747
and from char pointers and length.
4848
* Added ``memoryview`` wrapper type which is constructible from ``buffer_info``.
49+
* New syntax to call a Python function from C++ using keyword arguments and unpacking,
50+
e.g. ``foo(1, 2, "z"_a=3)`` or ``bar(1, *args, "z"_a=3, **kwargs)``.
51+
* Added ``py::print()`` function which replicates Python's API and writes to Python's
52+
``sys.stdout`` by default (as opposed to C's ``stdout`` like ``std::cout``).
53+
* Added ``py::dict`` keyword constructor:``auto d = dict("number"_a=42, "name"_a="World");``
54+
* Added ``py::str::format()`` method and ``_s`` literal:
55+
``py::str s = "1 + 2 = {}"_s.format(3);``
4956
* Various minor improvements of library internals (no user-visible changes)
5057

5158
1.8.1 (July 12, 2016)

include/pybind11/attr.h

Lines changed: 5 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,6 @@
1414

1515
NAMESPACE_BEGIN(pybind11)
1616

17-
template <typename T> struct arg_t;
18-
19-
/// Annotation for keyword arguments
20-
struct arg {
21-
constexpr explicit arg(const char *name) : name(name) { }
22-
23-
template <typename T>
24-
constexpr arg_t<T> operator=(const T &value) const { return {name, value}; }
25-
template <typename T, size_t N>
26-
constexpr arg_t<const T *> operator=(T const (&value)[N]) const {
27-
return operator=((const T *) value);
28-
}
29-
30-
const char *name;
31-
};
32-
33-
/// Annotation for keyword arguments with default values
34-
template <typename T> struct arg_t : public arg {
35-
constexpr arg_t(const char *name, const T &value, const char *descr = nullptr)
36-
: arg(name), value(value), descr(descr) { }
37-
T value;
38-
const char *descr;
39-
};
40-
41-
inline namespace literals {
42-
/// String literal version of arg
43-
constexpr arg operator"" _a(const char *name, size_t) { return arg(name); }
44-
}
45-
4617
/// Annotation for methods
4718
struct is_method { handle class_; is_method(const handle &c) : class_(c) { } };
4819

@@ -238,21 +209,14 @@ template <> struct process_attribute<arg> : process_attribute_default<arg> {
238209
};
239210

240211
/// Process a keyword argument attribute (*with* a default value)
241-
template <typename T>
242-
struct process_attribute<arg_t<T>> : process_attribute_default<arg_t<T>> {
243-
static void init(const arg_t<T> &a, function_record *r) {
212+
template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
213+
static void init(const arg_v &a, function_record *r) {
244214
if (r->class_ && r->args.empty())
245215
r->args.emplace_back("self", nullptr, handle());
246216

247-
/* Convert keyword value into a Python object */
248-
object o = object(detail::type_caster<typename detail::intrinsic_type<T>::type>::cast(
249-
a.value, return_value_policy::automatic, handle()), false);
250-
251-
if (!o) {
217+
if (!a.value) {
252218
#if !defined(NDEBUG)
253-
std::string descr(typeid(T).name());
254-
detail::clean_type_id(descr);
255-
descr = "'" + std::string(a.name) + ": " + descr + "'";
219+
auto descr = "'" + std::string(a.name) + ": " + a.type + "'";
256220
if (r->class_) {
257221
if (r->name)
258222
descr += " in method '" + (std::string) r->class_.str() + "." + (std::string) r->name + "'";
@@ -269,7 +233,7 @@ struct process_attribute<arg_t<T>> : process_attribute_default<arg_t<T>> {
269233
"Compile in debug mode for more information.");
270234
#endif
271235
}
272-
r->args.emplace_back(a.name, a.descr, o.release());
236+
r->args.emplace_back(a.name, a.descr, a.value.inc_ref());
273237
}
274238
};
275239

@@ -301,9 +265,6 @@ template <int Nurse, int Patient> struct process_attribute<keep_alive<Nurse, Pat
301265
static void postcall(handle args, handle ret) { keep_alive_impl(Nurse, Patient, args, ret); }
302266
};
303267

304-
/// Ignore that a variable is unused in compiler warnings
305-
inline void ignore_unused(const int *) { }
306-
307268
/// Recursively iterate over variadic template arguments
308269
template <typename... Args> struct process_attributes {
309270
static void init(const Args&... args, function_record *r) {
@@ -324,11 +285,6 @@ template <typename... Args> struct process_attributes {
324285
}
325286
};
326287

327-
/// Compile-time integer sum
328-
constexpr size_t constexpr_sum() { return 0; }
329-
template <typename T, typename... Ts>
330-
constexpr size_t constexpr_sum(T n, Ts... ns) { return n + constexpr_sum(ns...); }
331-
332288
/// Check the number of named arguments at compile time
333289
template <typename... Extra,
334290
size_t named = constexpr_sum(std::is_base_of<arg, Extra>::value...),

0 commit comments

Comments
 (0)