pybind11 cheatsheet documentation
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 18k
- Forks
- 2.3k
- Avg merge
- 5d 17h
- Merged PRs (30d)
- 10
Description
I have found the pybind11 documentation to be not so great for quickly trying to figure out "how the heck do I get from type A to type B". So I wrote my own notes. I'm interesting in getting these back into the official docs, but I am not sure what is the most appropriate form.
Here goes.
The important types:
py::handle- equivalent toPyObject*(no automatic refcounting)py::object- does automatic refcounting. Subclass of py::handle.
Conversions
PyObject* ↔ py::handle
This is a trivial conversion. These two types are basically totally equivalent.
PyObject *x;
py::handle h = x; // implicit conversion OK
x = h.ptr(); // no implicit conversion to raw pointer
py::handle (or subclass) → py::object (or subclass)
The syntax here works for both py::object, and any of its subclasses (e.g., py::str, etc)
http://pybind11.readthedocs.io/en/stable/reference.html#_CPPv26object
All of these are unchecked. Do an isinstance check beforehand if necessary. (Note that if you try to do anything with the py::object subclass, pybind11 will probably throw an exception at that point, so you probably aren't completely hosed. But casts to py::foo things are not checked at the point you do the cast!)
Common gotcha: you MUST pass a template argument to py::cast if you're casting from a PyObject*, it will silently do the wrong thing if you don't.
py::handle h;
// Copying
auto o = py::reinterpret_borrow<py::object>(h); // h can be PyObject*
// or
auto o = x.cast<py::object>();
// or
auto o = py::cast<py::object>(h); // h can be PyObject*
// equivalent to:
// Py_INCREF(x);
// THPObjectPtr o(x);
// Moving
auto o = py::reinterpret_steal<py::object>(h); // h can be PyObject*
// equivalent to:
// THPObjectPtr o(x);
py::object (or superclass) → py::handle
Stealing is pretty useful if you're trying to invoke a C API function that steals its argument.
py::object o;
// Borrows from o
py::handle h2 = o;
// refcount NOT increased; h2 is only live as long as o is
// Steals from o
py::handle h = o.release();
// o no longer valid
NB: a “copy” from object into handle doesn't make sense, because handle doesn't know how to manage its own memory.
NB2: these conversions are implemented by the implicit copy-constructor on py::handle,static casting the input py::object as a const py::handle& (in case you're like me and tried to find where in the code this conversion was implemented).
py::object → C++
- Checked conversion!
- Reference: http://pybind11.readthedocs.io/en/stable/reference.html#_CPPv2NK6handle4castEv
- Declared at: https://github.com/pybind/pybind11/blob/master/include/pybind11/pytypes.h#L171
- Source: https://github.com/pybind/pybind11/blob/master/include/pybind11/cast.h#L1613
- You can also use py::cast (explicit template argument needed): https://github.com/pybind/pybind11/blob/master/include/pybind11/cast.h#L1590
- Note that these are willing to do implicit conversions if necessary to get to the correct type; e.g., if you cast a py::float_ into an int, it will get truncated; if you cast an py::int_ into a std::string, it will get rendered as a string.
py::handle h; // or py::object
CppType x = h.cast<CppType>(); // may throw cast_error
// or
CppType x = py::cast<CppType>(h);
// x is a new copy unrelated to h
C++ → py::object
- Undocumented in Reference
- Source: https://github.com/pybind/pybind11/blob/master/include/pybind11/cast.h#L1602
- Return value policies apply: http://pybind11.readthedocs.io/en/stable/advanced/functions.html#return-value-policies
- Do NOT use a template argument, that is for a Python to C++ type conversion
CppType x;
py::object o = py::cast(x);
// or
py::object o = py::cast(x, return_value_policy::automatic);
// o is a new copy, but with a different policy it could be different
How do I...
// b = isinstance(x, ty)
py::handle x;
py::handle ty;
bool b = py::isinstance(x, ty);
// b = isinstance(x, str)
py::handle x;
bool b = py::isinstance<py::str>(x);
// b = isinstance(x, tuple)
py::handle x;
bool b = py::isinstance<py::tuple>(x);
// s = str(x)
py::handle x;
py::str s(x); // use the constructor
// b = hasattr(x, "something")
py::handle x;
bool b = py::hasattr(x, "something");
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing the existing reference documentation, especially the pytypes.h and cast.h declarations and the advanced/functions return-value policies page linked in the issue. Compare the proposed conversions and examples with the current official docs, then determine an appropriate documentation location and ensure the cheatsheet’s coverage and code examples are accurate.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, python
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100