Skip to content

Commit

Permalink
major cleanup of the whole codebase
Browse files Browse the repository at this point in the history
- new pybind11::base<> attribute to indicate a subclass relationship
- unified infrastructure for parsing variadic arguments in class_ and cpp_function
- use 'handle' and 'object' more consistently everywhere
  • Loading branch information
Wenzel Jakob committed Jan 17, 2016
1 parent 140546b commit ed3d23a
Show file tree
Hide file tree
Showing 20 changed files with 997 additions and 851 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ include_directories(${PYTHON_INCLUDE_DIR})
include_directories(include)

set(PYBIND11_HEADERS
include/pybind11/attr.h
include/pybind11/cast.h
include/pybind11/common.h
include/pybind11/complex.h
Expand Down Expand Up @@ -167,7 +168,7 @@ elseif (UNIX)
# Strip unnecessary sections of the binary on Linux/Mac OS
if(APPLE)
set_target_properties(example PROPERTIES MACOSX_RPATH ".")
set_target_properties(example PROPERTIES LINK_FLAGS "-undefined dynamic_lookup -dead_strip")
set_target_properties(example PROPERTIES LINK_FLAGS "-undefined dynamic_lookup ")
if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
add_custom_command(TARGET example POST_BUILD COMMAND strip -u -r ${PROJECT_SOURCE_DIR}/example/example.so)
endif()
Expand Down
2 changes: 1 addition & 1 deletion docs/advanced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ If not available, the signature may not be very helpful, e.g.:
FUNCTIONS
...
| myFunction(...)
| Signature : (MyClass, arg : SomeType = <SomeType object at 0x101b7b080>) -> None
| Signature : (MyClass, arg : SomeType = <SomeType object at 0x101b7b080>) -> NoneType
...
The first way of addressing this is by defining ``SomeType.__repr__``.
Expand Down
14 changes: 10 additions & 4 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,29 @@ Changelog

1.2 (not yet released)
--------------------------

* Optional: efficient generation of function signatures at compile time using C++14
* Switched to a simpler and more general way of dealing with function default arguments
Unused keyword arguments in function calls are now detected and cause errors as expected
* Switched to a simpler and more general way of dealing with function default
arguments. Unused keyword arguments in function calls are now detected and
cause errors as expected
* New ``keep_alive`` call policy analogous to Boost.Python's ``with_custodian_and_ward``
* New ``pybind11::base<>`` attribute to indicate a subclass relationship
* Improved interface for RAII type wrappers in ``pytypes.h``
* Use RAII type wrappers consistently within pybind11 itself. This
fixes various potential refcount leaks when exceptions occur
* Added new ``bytes`` RAII type wrapper (maps to ``string`` in Python 2.7).
* Made handle and related RAII classes const correct
* Made handle and related RAII classes const correct, using them more
consistently everywhere now
* Got rid of the ugly ``__pybind11__`` attributes on the Python side---they are
now stored in a C++ hash table that is not visible in Python
* Fixed refcount leaks involving NumPy arrays and bound functions
* Vastly improved handling of shared/smart pointers
* Removed an unnecessary copy operation in ``pybind11::vectorize``
* Fixed naming clashes when both pybind11 and NumPy headers are included
* Added conversions for additional exception types
* Documentation improvements (using multiple extension modules, smart pointers, other minor clarifications)
* Documentation improvements (using multiple extension modules, smart pointers,
other minor clarifications)
* unified infrastructure for parsing variadic arguments in class_ and cpp_function
* Fixed license text (was: ZLIB, should have been: 3-clause BSD)
* Python 3.2 compatibility

Expand Down
30 changes: 22 additions & 8 deletions docs/classes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -177,21 +177,35 @@ inheritance relationship:
std::string bark() const { return "woof!"; }
};
To capture the hierarchical relationship in pybind11, we must assign a name to
the ``Pet`` :class:`class_` instance and reference it when binding the ``Dog``
class.
There are two different ways of indicating a hierarchical relationship to
pybind11: the first is by specifying the C++ base class explicitly during
construction using the ``base`` attribute:

.. code-block:: cpp
py::class_<Pet>(m, "Pet")
.def(py::init<const std::string &>())
.def_readwrite("name", &Pet::name);
py::class_<Dog>(m, "Dog", py::base<Pet>() /* <- specify C++ parent type */)
.def(py::init<const std::string &>())
.def("bark", &Dog::bark);
Alternatively, we can also assign a name to the previously bound ``Pet``
:class:`class_` object and reference it when binding the ``Dog`` class:

.. code-block:: cpp
py::class_<Pet> pet(m, "Pet");
pet.def(py::init<const std::string &>())
.def_readwrite("name", &Pet::name);
py::class_<Dog>(m, "Dog", pet /* <- specify parent */)
py::class_<Dog>(m, "Dog", pet /* <- specify Python parent type */)
.def(py::init<const std::string &>())
.def("bark", &Dog::bark);
Instances then expose fields and methods of both types:
Functionality-wise, both approaches are completely equivalent. Afterwards,
instances will expose fields and methods of both types:

.. code-block:: python
Expand Down Expand Up @@ -242,14 +256,14 @@ The overload signatures are also visible in the method's docstring:
| Methods defined here:
|
| __init__(...)
| Signature : (Pet, str, int) -> None
| Signature : (Pet, str, int) -> NoneType
|
| set(...)
| 1. Signature : (Pet, int) -> None
| 1. Signature : (Pet, int) -> NoneType
|
| Set the pet's age
|
| 2. Signature : (Pet, str) -> None
| 2. Signature : (Pet, str) -> NoneType
|
| Set the pet's name
Expand Down
2 changes: 1 addition & 1 deletion docs/cmake.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ and that the pybind11 repository is located in a subdirectory named :file:`pybin
# Strip unnecessary sections of the binary on Linux/Mac OS
if(APPLE)
set_target_properties(example PROPERTIES MACOSX_RPATH ".")
set_target_properties(example PROPERTIES LINK_FLAGS "-undefined dynamic_lookup -dead_strip")
set_target_properties(example PROPERTIES LINK_FLAGS "-undefined dynamic_lookup ")
if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
add_custom_command(TARGET example POST_BUILD COMMAND strip -u -r ${PROJECT_BINARY_DIR}/example.so)
endif()
Expand Down
18 changes: 10 additions & 8 deletions docs/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,19 @@ Without reference counting

Return the ``PyObject *`` underlying a :class:`handle`.

.. function:: void handle::inc_ref() const
.. function:: const handle& handle::inc_ref() const

Manually increase the reference count of the Python object. Usually, it is
preferable to use the :class:`object` class which derives from
:class:`handle` and calls this function automatically.
:class:`handle` and calls this function automatically. Returns a reference
to itself.

.. function:: void handle::dec_ref() const
.. function:: const handle& handle::dec_ref() const

Manually decrease the reference count of the Python object. Usually, it is
preferable to use the :class:`object` class which derives from
:class:`handle` and calls this function automatically.
:class:`handle` and calls this function automatically. Returns a reference
to itself.

.. function:: void handle::ref_count() const

Expand Down Expand Up @@ -167,11 +169,11 @@ With reference counting
Move constructor; steals the object from ``other`` and preserves its
reference count.

.. function:: PyObject* object::release()
.. function:: handle object::release()

Release ownership of underlying ``PyObject *``. Returns raw Python object
pointer without decreasing its reference count and resets handle to
``nullptr``-valued pointer.
Resets the internal pointer to ``nullptr`` without without decreasing the
object's reference count. The function returns a raw handle to the original
Python object.

.. function:: object::~object()

Expand Down
10 changes: 10 additions & 0 deletions example/example5.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ class Dog : public Pet {
void bark() const { std::cout << "Woof!" << std::endl; }
};

class Rabbit : public Pet {
public:
Rabbit(const std::string &name) : Pet(name, "parrot") {}
};

void pet_print(const Pet &pet) {
std::cout << pet.name() + " is a " + pet.species() << std::endl;
}
Expand Down Expand Up @@ -62,9 +67,14 @@ void init_ex5(py::module &m) {
.def("name", &Pet::name)
.def("species", &Pet::species);

/* One way of declaring a subclass relationship: reference parent's class_ object */
py::class_<Dog>(m, "Dog", pet_class)
.def(py::init<std::string>());

/* Another way of declaring a subclass relationship: reference parent's C++ type */
py::class_<Rabbit>(m, "Rabbit", py::base<Pet>())
.def(py::init<std::string>());

m.def("pet_print", pet_print);
m.def("dog_bark", dog_bark);

Expand Down
4 changes: 4 additions & 0 deletions example/example5.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@

from example import Pet
from example import Dog
from example import Rabbit
from example import dog_bark
from example import pet_print

polly = Pet('Polly', 'parrot')
molly = Dog('Molly')
roger = Rabbit('Rabbit')
print(roger.name() + " is a " + roger.species())
pet_print(roger)
print(polly.name() + " is a " + polly.species())
pet_print(polly)
print(molly.name() + " is a " + molly.species())
Expand Down
22 changes: 12 additions & 10 deletions example/example5.ref
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
Rabbit is a parrot
Polly is a parrot
Polly is a parrot
Molly is a dog
Molly is a dog
Woof!
The following error is expected: Incompatible function arguments. The following argument types are supported:
1. (Dog) -> NoneType

Callback function 1 called!
False
Callback function 2 called : Hello, x, True, 5
5
func(43) = 44
func(43) = 44
Payload constructor
Payload copy constructor
Payload move constructor
Payload destructor
Payload destructor
Payload destructor
Rabbit is a parrot
Polly is a parrot
Molly is a dog
The following error is expected: Incompatible function arguments. The following argument types are supported:
1. (example.Dog) -> NoneType

Callback function 1 called!
False
Callback function 2 called : Hello, x, True, 5
5
func(43) = 44
Loading

0 comments on commit ed3d23a

Please sign in to comment.