-- GHDL Run Time (GRT) - Wave option file package for reading the tree. -- Copyright (C) 2016 Jonas Baggett -- -- GHDL is free software; you can redistribute it and/or modify it under -- the terms of the GNU General Public License as published by the Free -- Software Foundation; either version 2, or (at your option) any later -- version. -- -- GHDL is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- for more details. -- -- You should have received a copy of the GNU General Public License -- along with GCC; see the file COPYING. If not, write to the Free -- Software Foundation, 59 Temple Place - Suite 330, Boston, MA -- 02111-1307, USA. -- -- As a special exception, if other files instantiate generics from this -- unit, or you link this unit with other files to produce an executable, -- this unit does not by itself cause the resulting executable to be -- covered by the GNU General Public License. This exception does not -- however invalidate any other reasons why the executable file might be -- covered by the GNU Public License. -- Description: See package specifications with Grt.Errors; use Grt.Errors; with Grt.Wave_Opt.File; use Grt.Wave_Opt.File; package body Grt.Wave_Opt.Design is -- Find the element that matches the name given. Starts with the element -- given, then go thru all its siblings function Find_Cursor (Name : String; Parent : Match_List; Is_Signal : Boolean := False) return Match_List; -- If the name of the current design object matches with the child tree -- element given in parameter (Elem_Acc), this procedure is called to add -- the latter to the list of all the child tree elements that match a design -- object. -- A list needs to be done, because if /top/sub/a, /top/sub/b and /top/sub/c -- exist in the design and if we have /top/sub/a, /top/*/b and /top/**/c in -- the tree, then a list of the child tree elements of /top will be done -- with sub, * and ** so that /top/sub/a, /top/sub/b and /top/sub/c can be -- matched with respectively /top/sub/a, /top/*/b and /top/**/c procedure Match_List_Append (List : in out Match_List; Tree_Elem : Elem_Acc); -- TODO : Deallocate the list somewhere, but the memory gain shouldn't be -- significative function Get_Top_Cursor (Tree_Index : Tree_Index_Type; Name : Ghdl_C_String) return Match_List is Root : Match_List; begin if State = Write_File and then Trees (Tree_Index).Next_Child = null then Write_Tree_Comment (Tree_Index); end if; Root := new Match_Elem_Type'(Trees (Tree_Index), null); return Get_Cursor (Root, Name); end Get_Top_Cursor; function Get_Cursor (Parent : Match_List; Name : Ghdl_C_String; Is_Signal : Boolean := False) return Match_List is Tree_Elem_Cursor : Elem_Acc; Last_Updated : Boolean; Str_Name : constant String := Name (1 .. strlen (Name)); begin case State is when Write_File => Tree_Elem_Cursor := Parent.Tree_Elem; Last_Updated := True; Update_Tree (Cursor => Tree_Elem_Cursor, Last_Updated => Last_Updated, Elem_Expr => Str_Name, Level => Tree_Elem_Cursor.Level + 1); if Is_Signal then Write_Signal_Path (Tree_Elem_Cursor); end if; return new Match_Elem_Type'(Tree_Elem_Cursor, null); when Display_Tree => return Find_Cursor (Str_Name, Parent, Is_Signal); when Display_All => return null; end case; end Get_Cursor; function Find_Cursor (Name : String; Parent : Match_List; Is_Signal : Boolean := False) return Match_List is Tree_Elem_Cursor : Elem_Acc; Parent_Cursor, List : Match_List; -- function Match_Expr return Boolean is begin if Tree_Elem_Cursor.Expr.all = Name then return True; elsif Tree_Elem_Cursor.Expr.all = "*" then -- Returns true in the following cases : -- Design object : /top/a | Tree element : /top/* -- Design object : /top/sub/... | Tree element : /top/*/... if Is_Signal xor Tree_Elem_Cursor.Next_Child /= null then return True; end if; elsif Tree_Elem_Cursor.Expr.all = "**" then -- Returns true in the following cases : -- Design object : /top/sub/... | Tree element : /top/** -- Design object : /top/a | Tree element : /top/** -- But will return false in the following case : -- Design object : /top/a | Tree element : /top/**/x if not Is_Signal or else Tree_Elem_Cursor.Next_Child = null then return True; end if; end if; return False; end Match_Expr; function Get_Cursor_Kind return Elem_Kind_Type is begin if Tree_Elem_Cursor.Expr.all = "**" then return Recursion; elsif Is_Signal then return Signal; else return Pkg_Entity; end if; end Get_Cursor_Kind; begin Parent_Cursor := Parent; loop exit when Parent_Cursor = null; Tree_Elem_Cursor := Parent_Cursor.Tree_Elem.Next_Child; if Parent_Cursor.Tree_Elem.Expr.all = "**" then -- Add the current tree element to the list in the following cases: -- Design object : /top/y/x | Tree element : /top/**/x -- Design object : /top/y/x/... | Tree element : /top/**/x/... -- where x matchs the Name parameter, ** is the parent expression if Tree_Elem_Cursor /= null and then Tree_Elem_Cursor.Expr.all = Name then Match_List_Append (List, Tree_Elem_Cursor); -- Add the parent tree element (**) to the list in the following -- cases: -- Design object : /top/y/x/... | Tree element : /top/** -- Design object : /top/y/x | Tree element : /top/** -- But it won't do it in the following case: -- Design object : /top/y/x | Tree element : /top/**/z -- as x != z elsif not Is_Signal or else Tree_Elem_Cursor = null then Match_List_Append (List, Parent_Cursor.Tree_Elem); end if; end if; loop exit when Tree_Elem_Cursor = null; if Match_Expr then Tree_Elem_Cursor.Kind := Get_Cursor_Kind; Match_List_Append (List, Tree_Elem_Cursor); end if; Tree_Elem_Cursor := Tree_Elem_Cursor.Next_Sibling; end loop; Parent_Cursor := Parent_Cursor.Next; end loop; return List; end Find_Cursor; procedure Match_List_Append (List : in out Match_List; Tree_Elem : Elem_Acc) is begin List := new Match_Elem_Type'(Tree_Elem => Tree_Elem, Next => List); end Match_List_Append; function Is_Displayed (Cursor : Match_List) return Boolean is begin if State /= Display_Tree or else Cursor /= null then return True; end if; return False; end Is_Displayed; -- Read the whole sub tree given and check if every element was found in -- design. Called by Last_Checks procedure Check_Sub_Tree_If_All_Found (Previous_Cursor : Elem_Acc); procedure Last_Checks is begin if Wave_Opt.State = Display_Tree then for Index in Tree_Index_Type'Range loop Check_Sub_Tree_If_All_Found (Trees (Index).Next_Child); end loop; end if; -- TODO : The tree of the wave option file should be deallocated here, -- but the memory gain shouldn't be significative end Last_Checks; procedure Check_Sub_Tree_If_All_Found (Previous_Cursor : Elem_Acc) is Cursor : Elem_Acc; begin Cursor := Previous_Cursor; while Cursor /= null loop if Cursor.Kind = Not_Found then Warning_S; Diag_C_Context (Cursor); Diag_C (Cursor.Expr.all); Diag_C (" : first element of the path not found in design."); Diag_C (" More references may follow"); Warning_E; elsif Cursor.Next_Child = null and then Cursor.Kind = Pkg_Entity then Warning_S; Diag_C_Context (Cursor); Diag_C (Cursor.Expr.all); Diag_C (" is not a signal"); Warning_E; else Check_Sub_Tree_If_All_Found (Cursor.Next_Child); end if; Cursor := Cursor.Next_Sibling; end loop; end Check_Sub_Tree_If_All_Found; end Grt.Wave_Opt.Design; 4' href='#n184'>184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
.. _basics:

First steps
###########

This sections demonstrates the basic features of pybind11. Before getting
started, make sure that development environment is set up to compile the
included set of test cases.


Compiling the test cases
========================

Linux/macOS
-----------

On Linux  you'll need to install the **python-dev** or **python3-dev** packages as
well as **cmake**. On macOS, the included python version works out of the box,
but **cmake** must still be installed.

After installing the prerequisites, run

.. code-block:: bash

   mkdir build
   cd build
   cmake ..
   make check -j 4

The last line will both compile and run the tests.

Windows
-------

On Windows, only **Visual Studio 2015** and newer are supported since pybind11 relies
on various C++11 language features that break older versions of Visual Studio.

.. Note::

    To use the C++17 in Visual Studio 2017 (MSVC 14.1), pybind11 requires the flag
    ``/permissive-`` to be passed to the compiler `to enforce standard conformance`_. When
    building with Visual Studio 2019, this is not strictly necessary, but still advised.

..  _`to enforce standard conformance`: https://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view=vs-2017

To compile and run the tests:

.. code-block:: batch

   mkdir build
   cd build
   cmake ..
   cmake --build . --config Release --target check

This will create a Visual Studio project, compile and run the target, all from the
command line.

.. Note::

    If all tests fail, make sure that the Python binary and the testcases are compiled
    for the same processor type and bitness (i.e. either **i386** or **x86_64**). You
    can specify **x86_64** as the target architecture for the generated Visual Studio
    project using ``cmake -A x64 ..``.

.. seealso::

    Advanced users who are already familiar with Boost.Python may want to skip
    the tutorial and look at the test cases in the :file:`tests` directory,
    which exercise all features of pybind11.

Header and namespace conventions
================================

For brevity, all code examples assume that the following two lines are present:

.. code-block:: cpp

    #include <pybind11/pybind11.h>

    namespace py = pybind11;

Some features may require additional headers, but those will be specified as needed.

.. _simple_example:

Creating bindings for a simple function
=======================================

Let's start by creating Python bindings for an extremely simple function, which
adds two numbers and returns their result:

.. code-block:: cpp

    int add(int i, int j) {
        return i + j;
    }

For simplicity [#f1]_, we'll put both this function and the binding code into
a file named :file:`example.cpp` with the following contents:

.. code-block:: cpp

    #include <pybind11/pybind11.h>

    int add(int i, int j) {
        return i + j;
    }

    PYBIND11_MODULE(example, m) {
        m.doc() = "pybind11 example plugin"; // optional module docstring

        m.def("add", &add, "A function which adds two numbers");
    }

.. [#f1] In practice, implementation and binding code will generally be located
         in separate files.

The :func:`PYBIND11_MODULE` macro creates a function that will be called when an
``import`` statement is issued from within Python. The module name (``example``)
is given as the first macro argument (it should not be in quotes). The second
argument (``m``) defines a variable of type :class:`py::module_ <module>` which
is the main interface for creating bindings. The method :func:`module_::def`
generates binding code that exposes the ``add()`` function to Python.

.. note::

    Notice how little code was needed to expose our function to Python: all
    details regarding the function's parameters and return value were
    automatically inferred using template metaprogramming. This overall
    approach and the used syntax are borrowed from Boost.Python, though the
    underlying implementation is very different.

pybind11 is a header-only library, hence it is not necessary to link against
any special libraries and there are no intermediate (magic) translation steps.
On Linux, the above example can be compiled using the following command:

.. code-block:: bash

    $ c++ -O3 -Wall -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` example.cpp -o example`python3-config --extension-suffix`

For more details on the required compiler flags on Linux and macOS, see
:ref:`building_manually`. For complete cross-platform compilation instructions,
refer to the :ref:`compiling` page.

The `python_example`_ and `cmake_example`_ repositories are also a good place
to start. They are both complete project examples with cross-platform build
systems. The only difference between the two is that `python_example`_ uses
Python's ``setuptools`` to build the module, while `cmake_example`_ uses CMake
(which may be preferable for existing C++ projects).

.. _python_example: https://github.com/pybind/python_example
.. _cmake_example: https://github.com/pybind/cmake_example

Building the above C++ code will produce a binary module file that can be
imported to Python. Assuming that the compiled module is located in the
current directory, the following interactive Python session shows how to
load and execute the example:

.. code-block:: pycon

    $ python
    Python 2.7.10 (default, Aug 22 2015, 20:33:39)
    [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.1)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import example
>>> example.add(1, 2)
        3L
    >>>

.. _keyword_args:

Keyword arguments
=================

With a simple code modification, it is possible to inform Python about the
names of the arguments ("i" and "j" in this case).

.. code-block:: cpp

    m.def("add", &add, "A function which adds two numbers",
          py::arg("i"), py::arg("j"));

:class:`arg` is one of several special tag classes which can be used to pass
metadata into :func:`module_::def`. With this modified binding code, we can now
call the function using keyword arguments, which is a more readable alternative
particularly for functions taking many parameters:

.. code-block:: pycon

    >>> import example
    >>> example.add(i=1, j=2)
    3L

The keyword names also appear in the function signatures within the documentation.

.. code-block:: pycon

    >>> help(example)

    ....

    FUNCTIONS
        add(...)
            Signature : (i: int, j: int) -> int

            A function which adds two numbers

A shorter notation for named arguments is also available:

.. code-block:: cpp

    // regular notation
    m.def("add1", &add, py::arg("i"), py::arg("j"));
    // shorthand
    using namespace pybind11::literals;
    m.def("add2", &add, "i"_a, "j"_a);

The :var:`_a` suffix forms a C++11 literal which is equivalent to :class:`arg`.
Note that the literal operator must first be made visible with the directive
``using namespace pybind11::literals``. This does not bring in anything else
from the ``pybind11`` namespace except for literals.

.. _default_args:

Default arguments
=================

Suppose now that the function to be bound has default arguments, e.g.:

.. code-block:: cpp

    int add(int i = 1, int j = 2) {
        return i + j;
    }

Unfortunately, pybind11 cannot automatically extract these parameters, since they
are not part of the function's type information. However, they are simple to specify
using an extension of :class:`arg`:

.. code-block:: cpp

    m.def("add", &add, "A function which adds two numbers",
          py::arg("i") = 1, py::arg("j") = 2);

The default values also appear within the documentation.

.. code-block:: pycon

    >>> help(example)

    ....

    FUNCTIONS
        add(...)
            Signature : (i: int = 1, j: int = 2) -> int

            A function which adds two numbers

The shorthand notation is also available for default arguments:

.. code-block:: cpp

    // regular notation
    m.def("add1", &add, py::arg("i") = 1, py::arg("j") = 2);
    // shorthand
    m.def("add2", &add, "i"_a=1, "j"_a=2);

Exporting variables
===================

To expose a value from C++, use the ``attr`` function to register it in a
module as shown below. Built-in types and general objects (more on that later)
are automatically converted when assigned as attributes, and can be explicitly
converted using the function ``py::cast``.

.. code-block:: cpp

    PYBIND11_MODULE(example, m) {
        m.attr("the_answer") = 42;
        py::object world = py::cast("World");
        m.attr("what") = world;
    }

These are then accessible from Python:

.. code-block:: pycon

    >>> import example
    >>> example.the_answer
    42
    >>> example.what
    'World'

.. _supported_types:

Supported data types
====================

A large number of data types are supported out of the box and can be used
seamlessly as functions arguments, return values or with ``py::cast`` in general.
For a full overview, see the :doc:`advanced/cast/index` section.