Commit 5dab1e06 authored by Baptiste Esteban's avatar Baptiste Esteban
Browse files

Write an example of extension using Pylene-numpy

parent e239e4bc
Pipeline #27350 passed with stages
in 12 minutes and 34 seconds
Writing an extension module
===========================
When writing an algorithm in C++ is great for performance issue but it is not
easy to prototype algorithms in this language. To solve this problem, Pylene
provides a library, ``Pylene-numpy``, which makes the the automatic conversion
between Pylene images and Numpy arrays, thanks to the Pybind11's
``type_caster``.
In the following, it is explained how to make use of this library to create an
extension module.
Step 1: Setup the project
--------------------------
At first, a ``conanfile.txt`` is created.
.. code-block:: text
[generators]
......@@ -15,17 +26,30 @@ Step 1: Setup the project
pybind11/2.6.2
[options]
pylene:fPIC=True
pylene:fPIC=True # or pylene:shared=True
In this conanfile, two Conan's generators are used: the ``cmake`` generator and
the ``cmake_find_package`` generator. In the previous section, it is specified
that the ``cmake_find_package`` is prefered but an issue in the Conan Center
Index makes it unusable for Pybind11 (see `here
<https://github.com/conan-io/conan-center-index/pull/4445>`_ for more details).
For the same reason, the Pybind11 package is not a runtime dependency of the
``Pylene-numpy`` library and should be specified as a dependency of the
extension project. Finally, the `fPIC` option is specified as an option for
Pylene, which enable to use have the ``Pylene-numpy`` library during the
dependencies installation.
Then, bellow is the ``CMakeLists.txt``:
.. code-block:: cmake
cmake_minimum_required(VERSION 3.14)
project(pylene_extension)
if (EXISTS "${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake")
include("${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake")
conan_set_rpath()
if (NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake")
message(FATAL_ERROR "Conan dit not run. Please run conan install.")
endif()
include("${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake")
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_BINARY_DIR}" "${CONAN_BUILD_DIRS_PYBIND11}")
find_package(Pylene REQUIRED)
......@@ -35,9 +59,12 @@ Step 1: Setup the project
target_sources(pylene_extension PRIVATE pylene_extension.cpp)
target_link_libraries(pylene_extension PUBLIC Pylene::Pylene-numpy)
Step 2: Writing an extension
----------------------------
Bellow is an exemple of an extension module:
.. code-block:: cpp
#include <pln/core/image_cast.hpp>
......@@ -68,9 +95,32 @@ Step 2: Writing an extension
m.def("iota", &iota);
}
There are a few important things to note about this code. At first,
**the header** ``<pln/core/image_cast.hpp>``
**must be included in all the compilation unit of the extension module**.
In this header, the ``type_caster`` converting Pylene images into Numpy
arrays and inversely. If not included, some undefined behavior may happen.
Then, a ``iota`` function is defined. This function fill inplace a 2D image with
unsigned element on 8 bits. The argument of this function is a
``mln::ndbuffer_image``, the type-erased version of the Pylene images, where the
type and the dimension of the image are stored dynamically. However, it is not
considered as an image by the library and cannot be manipulated directly: it has
to be casted to a Pylene image, as it is done in the first lines of the
function, thanks to the ``cast_to`` method. This method takes two template
parameters: the type of the image and its dimension. If it matches the ones
stored dynamically, the image is converted. Else, ``nullptr`` is returned by the
method.
Finally, the last lines define the Python module, thanks to Pybind11. It is
important to note that the ``pln::init_pylena_numpy`` is called at the first
line of the module extension. **It should be called at the first line of the module definition for an extension module.**
Step 3: Using the extension
---------------------------
Finally, bellow is an example of how to use the simple module developped above.
>>> from pylene_extension import iota
>>> import numpy as np
>>> img = np.zeros((10, 10)).astype(np.float64)
......
Introduction
============
The Pylene library makes possible to expose its features in Python. To this aim, it provides two components :
The Pylene library makes possible to expose its features in Python. To this aim,
it provides two components :
* The ``Pylene-numpy`` library, which converts Pylene images into Numpy arrays.
* The ``pylena`` module, which binds some Pylene algorithms in Python.
Currently, the ``pylena`` module is under development and is empty. However, it is possible to create
a Python module using `Pybind11 <https://pybind11.readthedocs.io>`_ and the ``Pylene-numpy`` library. This is described in the next section.
Currently, the ``pylena`` module is under development and is empty. However, it
is possible to create a Python module using `Pybind11
<https://pybind11.readthedocs.io>`_ and the ``Pylene-numpy`` library. This is
described in the next section.
Installation
^^^^^^^^^^^^
Before continuing, it is advised to read :ref:doc:`this section</tutorial/installation>` about the Pylene installation.
This subsection describe how to get the ``Pylene-numpy`` library. Two methods are explained :
This subsection describe how to get the ``Pylene-numpy`` library. Two methods
are explained :
* Getting ``Pylene-numpy`` using Conan to use it in a project.
* Building the ``Pylene-numpy`` library from sources.
In any cases, on Linux, make sure to get the Pylene library using the ``Position Independent Code`` compiler option
since Python modules on Linux are dynamic libraries. On Windows, the standard installation steps will install the Python
In any cases, on Linux, make sure to get the Pylene library using the ``Position
Independent Code`` compiler option since Python modules on Linux are dynamic
libraries. On Windows, the standard installation steps will install the Python
components.
Using Conan (preferred)
-----------------------
When writing a `conanfile` to get the `Pylene` library, some ``options`` have to be added to get the Python components.
Bellow is an exemple of a `conanfile.txt`, where the `fPIC` option has been added for Pylene.
When writing a `conanfile` to get the `Pylene` library, some ``options`` have to
be added to get the Python components. Bellow is an exemple of a
`conanfile.txt`, where the `fPIC` option has been added for Pylene.
.. code-block:: text
......@@ -40,11 +46,15 @@ Bellow is an exemple of a `conanfile.txt`, where the `fPIC` option has been adde
[options]
pylene:fPIC=True # Or pylene:shared=True
If the ``pylene:shared`` option is set to ``True``, append the Conan's option
``--build pylene`` because the prebuilt library is linked to the builder Python
library, which should not be the one in the user system.
Building Pylene using CMake
---------------------------
People willing to build the Pylene library, such as Pylene's developpers, should execute the following command
to build the Python components.
People willing to build the Pylene library, such as Pylene's developpers, should
execute the following command to build the Python components.
.. code-block:: console
......@@ -53,11 +63,14 @@ to build the Python components.
$ cmake .. -DPYLENE_BUILD_PYTHON=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON
$ make -j4
As explained above, the `fPIC` option has been added to the Conan install command. Futhermore, two CMake's options
are added:
As explained above, the `fPIC` option has been added to the Conan install
command. Futhermore, two CMake's options are added:
* ``-DPYLENE_BUILD_PYTHON=ON`` to enable the build process of the Python components.
* ``-DCMAKE_POSITION_INDEPENDENT_CODE=ON`` to compile using the `fPIC` flags of the compiler.
If CMake is runned with ``-DPYLENE_BUILD_PYTHON=ON`` but not with ``-DCMAKE_POSITION_INDEPENDENT_CODE=ON``, a warning will be shown during the build system generation
but it will not prevent the build process to run. So during the build process, a linker error should be raised for the building of the ``pylena`` module.
\ No newline at end of file
If CMake is runned with ``-DPYLENE_BUILD_PYTHON=ON`` but not with
``-DCMAKE_POSITION_INDEPENDENT_CODE=ON``, a warning will be shown during the
build system generation but it will not prevent the build process to run. So
during the build process, a linker error should be raised for the building of
the ``pylena`` module.
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment