========================
Pyste & Py++  comparison
========================

.. contents:: Table of contents

----------------------
What is `Py++`_?
----------------------

.. include:: ../definition.rest

-----------------
What is `Pyste`_?
-----------------

`Pyste`_ is a `Boost.Python`_ code generator. The user specifies the classes and
functions to be exported using a simple interface file, which following the
`Boost.Python`_'s philosophy, is simple `Python`_ code. `Pyste`_ then uses
`GCC-XML`_ to parse all the headers and extract the necessary information to
automatically generate C++ code.

--------
Preamble
--------

If you are reading this document, I can assume that you know what `Boost.Python`_,
`Pyste`_ and `Py++`_ are. This document compares `Pyste`_ and `Py++`_.
I am going to compare:

    * user interface

    * design

    * dependencies

    * features list:

        * supported `Boost.Python`_ components

        * nice features

I did not develop `Pyste`_, so it is possible I made few mistakes in my
analyzes. If you identify one, please report it. I will try to fix it, as quick
as possible. In the past, I created bindings to few projects using `Pyste`_.
Code, generated by `Pyste`_, was pretty good and gave me a good start both with
my projects and with `Boost.Python`_ library. As for me, there are two main
problems with `Pyste`_:

    1. It is time-consuming operation to maintain `Pyste`_ scripts in a big,
       dynamic project.

    2. It is very difficult to customize generated code. I will provide few
       examples later.

I tried to fix `Pyste`_. At first, I developed `pygccxml`_ and tried to replace
relevant `Pyste`_ functionality. I did not like the result. After this, I dropped
the idea to fix `Pyste`_ and decided to develop new code generator - `Py++`_.
Later you will find few points, which explains, why I decided not to fix `Pyste`_.

Have a nice reading.

--------------
User interface
--------------

Pyste
-----

Carefully read `Pyste`_ definition -

  "... The user specifies the classes and functions to be exported using a simple
  interface file, which following the `Boost.Python`_'s philosophy, is simple
  `Python`_ code. ..."


Simple interface file is an advantage and a disadvantage at the same time. The
advantage is obvious: it is easy to start to use. The disadvantage is less
obvious - you cannot work on whole exported library at once.

    1. Try to exclude all functions, that nth argument has some specific type.

    2. Try to exclude\\leave all classes, which belongs to some namespace.

    3. Maintenance. Every time you add new file\\class to your project you should
       modify\\create `Pyste`_ interface files.

    4. Try to set call policies to functions based on some detail\\fact.

First and second example could be solved, but it is neither easy, nor obvious.
You should understand `Pyste`_ implementation details. Third example is solvable
if you are lucky and ready to write few `Python`_\\shell scripts.

  "... AllFromHeader is broken in some cases. Until it is fixed, use at you own
  risk. ..."

  ---`Pyste`_ documentation.

I have more examples, but I think you've got the idea.

Py++
----

`Py++`_ has 2 user interfaces:

    1. GUI - small and simple graphic user interface, which does not request from
       user any knowledge about `Boost.Python`_ or `Py++`_. You can see
       its `screenshot`_.

    2. API - object-oriented framework, that helps you to create code generator,
       that suites your needs. `Py++`_ framework consists 3 packages:

        1. Code creators package. The only responsibility of classes in this
           package is to create code. Those classes do not care where code is
           going to be written. Neither they care about the order of generated
           code.

        2. Module creator package. This is code creators factory. Classes in this
           package, analyze C++ declarations and creates relevant code creators.

        3. File writers package. This package contains classes that write
           generated code to file(s).

The good news: it is very easy to evaluate `Py++`_, using GUI. The bad
news is that you should learn an other set of API's in order to complete your
task. It is not as awful as it sounds, but still there is some learning curve.

------
Design
------

Pyste
-----

`Pyste`_ design is not bad at all, but there were few mistakes made. First of all
current situation. There is  a class hierarchy that represents C++ declarations
and types. There is *Exporter*'s hierarchy. There are 2 unrelated classes
*SingleCodeUnit* and *MultipleCodeUnit*.

Class *Exporter* has few responsibilities:

    1. to create code

    2. to write code into code unit

    3. to decide what, how and in which order declarations should be exported
       (excluded)

Classes *SingleCodeUnit* and *MultipleCodeUnit* also has few responsibilities:

    1. to write code into files

    2. to control the order of written code

Py++
----

One of the biggest weaknesses of `Pyste`_ is a lack of good `GCC-XML`_ front-end
and this fact cause `Pyste`_ to generate not optimal code. I will prove this
later. In order to avoid such weakness, before I have created `Py++`_,
I created `pygccxml`_. `pygccxml`_ is a stand-alone project, which provides few
things:

    * hierarchy of C++ declarations

    * hierarchy of C++ types

    * few parsing strategies:

      + all files will be parsed as it was one file that includes all them

      + every file will be parsed alone, after this, duplicated declarations
        and types will be removed

`pygccxml`_ contributes in few ways to `Py++`_:

    + `Py++`_ has nothing to do with code parsing. Theoretically
      an other back-end could be added to `pygccxml`_ without changing even one
      line of code within `Py++`_.

    + `pygccxml`_ has type traits. A lot of type traits algorithms from
      `boost.type_traits`_ library has been implemented. `Py++`_ makes
      an extensive use of them:

      * identify "call policies" algorithm

      * code creator that generates body of "overridden" virtual functions:

        .. code-block:: C++

          struct expensive_to_copy{...};

        .. code-block:: C++

          void do_smth( expensive_to_copy* x, const expensive_to_copy& y ){...}

        .. code-block:: C++

          void
          do_smth(expensive_to_copy* x, const expensive_to_copy& y){
              //Pyste generates the following code
              //call_method< void >(self, "do_smth", x, y);
              //Py++ generates the following code
              *this->get_override("do_smth")( boost::python::ptr(x), boost::ref(y) );
              //------------------------------^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^
          }

        Do you see the difference? This is a prove to the point I made earlier:
        `Pyste`_ generates not optimal code.

    + Do you remember first 3 problems, I talked about?

      1. Try to exclude all functions, that nth argument has some specific type.

      2. Try to exclude\\leave all classes, which belongs to some namespace.

      3. Maintenance. Every time you add new file\\class to your project you should
         modify\\create `Pyste`_ interface files.

      They are solved by `pygccxml`_ package. Please take a look on `pygccxml`_
      `query interface`__ documentation.

.. __ : ./../../pygccxml/query_interface.html

Now about mistakes. There is a gold rule: one class, one responsibility. `Pyste`_
breaks this rule. One more time *Exporter* class responsibilities:

    1. to create code

    2. to write code into code unit

    3. to decide what, how and in which order declarations should be exported
       (excluded)

What is wrong with this? In some places the logic of code generation is complex.
`Pyste`_ makes this situation worse. In order to understand my point try to see,
what is going on, in "ClassExporter.py" file. Class *ClassExporter* knows
everything about internal exporters, more over *ClassExporter* is responsible to
export all its base classes before it exports itself. This is just wrong.
`Py++`_ implements better solution. `Py++`_ has code creators class
hierarchy and factory, that creates those code creators based on given
declarations. The questions like:

    * what should be the order of exporting declarations

    * could \\ should the declaration be exported

    * what are the call policies of the function

    * what is the class held type

solved by the factory. The only thing that left to code creators is to create code.
By the way, it is not an easy task to fix this specific problem in `Pyste`_.
Serious re-factoring should be done. `Py++`_ defines *compound_t* code
creator. *module_t*, *module_body_t*, *class_t* - are typical examples of
compound code creators. They do know few code creators, but that is all.

An other weakness is a relationship between *Exporter*'s and code units. In
order to write code into code unit, *Exporter* should specify section name and
text. There are few problems with this. First of all, this tight coupling is
unnecessary. In order to add new *Exporter* you should understand the underlying
protocol and may be to modify code unit. Try to add *Exporter* that exposes
get\\set functions as property. It is not an easy task. An other problem, I see
here, is that code unit is some kind of *Exporter*. Code unit also creates code.
I did not fill good with this design. So I decided, that in `Py++`_ code
should be created only by code creators. This decision simplifies a lot of
things:

    * code creators does not depend on file writers

    * file writers do not have to know all code creators

    * code creators set is not closed and could be extended

    * user can place custom code creator almost anywhere

    * code creators can take into account code that is going to be generated by
      other code creators. For example namespace aliases or include directives.

    * ...

------------
Dependencies
------------
Both `Pyste`_ and `Py++`_ introduce one external dependency. In order to
parse XML `Pyste`_ uses `elementtree`_. On the other side `Py++`_
depends on `pygccxml`_ project.

-------------
Features list
-------------
`Py++`_ supports almost all features `Pyste`_ implements. `Py++`_,
version 0.8.0, does not implements the following functionality, implemented by `Pyste`_:

    * *pow* operator

    * good documentation

Here you can find the complete features list of `Py++`_.

Features unique to `Py++`_:

    * `Py++`_ exposes protected member functions

    * `Py++`_, in most cases, will automatically detect class held type

    * `Py++`_ creates implicit conversion code for:

       + casting constructors

       + casting operators

       + smart pointers of derived and base class

    * class wrappers generated using `Boost.Python`_ wrapper class

    * operator() always exposed ( this is not the case with `Pyste`_ )

    * operators defined in base class could be redefined/exposed in derived class

    * `Py++`_ exposes bit fields member variables

Nice features list
------------------

Both `Pyste`_ and `Py++`_ generate working code. As we already saw in some
cases `Py++`_ do better job. `Py++`_ allows the following customization on
generated code:

    * To define std and user directories. *include_t* code creator will take
      those directories into account.

    * To define namespace alias.

      .. code-block:: C++

        namespace dt = boost::date_time;

      All code, which is generated after this statement, will use ``dt`` instead of
      ``boost::date_time``. This allows `Py++`_ to create user-friendly code.

    * Classes and functions support 2 modes of code generation. Example:

      .. code-block:: C++

        struct world{
            void set(std::string msg) { this->msg = msg; }
            std::string greet() { return msg; }
            std::string msg;
        };

      First mode:

      .. code-block:: C++

        class_<world>("world")
           .def("greet", &world::greet)
           .def("set", &world::set)
        ;


      Second mode:

      .. code-block:: C++

        if( true ){
            typedef class_<world> world_exposer_t;
            world_exposer_t world_exposer;
            boost::python::scope world_scope( exposer );
            world_exposer.def( "greet", ( std::string ( world::* )() )( &world::greet ) );
            world_exposer.def( "set", ( void ( world::* )(std::string) )( &world::set ) );
        }

      Second mode is better then first, because:

        1. It is easier to understand compilation error.

        2. If in future a developer decides to create overload to some function,
           this code will continue to compile.

    * `Py++`_ has small nice future - "license". User can specify the
      license and it will appear in every generated file.

    * `Py++`_ allows user to define custom call policies resolver. See
      boost.date_time example

    * `Py++`_ allows user to create custom code creators. See
      "custom_code_creator" example.

    * real world examples:

      + EasyBMP

      + boost.date_time

      + Qt.XML

----------
Conclusion
----------

If I were you I would choose `Py++`_ to create bindings for your project.
For very small projects or for educational reasons you may use `Py++`_.GUI.
For big projects, you need flexibility and power of `Py++`_.

----
P.S.
----

This comparison was a little unfair. First of all `Pyste`_ is no more under
active development\\support. Second, `Pyste`_ has been written 2 years ago and
had different goal. The following definitions will help you to understand the main
difference between `Pyste`_ and `Py++`_.

 `Pyste`_
   `Pyste`_ is `Boost.Python`_ code generator.

 `Py++`_
   .. include:: ../definition.rest

`Pyste`_ and `Py++`_ have been created to handle different tasks, hence
the difference in design, user interface and complexity. Bruno da Silva de
Oliveira, the `Pyste`_ author, understands the problems, I raised here. He
thought about them, long before I created `Py++`_. But unfortunately, lack
of time and motivation prevents him to work on `Pyste`_.

.. _`screenshot` : ./../documentation/tutorials/pyplusplus_gui.html
.. _`Py++` : ./../pyplusplus.html
.. _`pygccxml` : ./../../pygccxml/pygccxml.html
.. _`Pyste`: http://www.boost.org/libs/python/doc/index.html
.. _`Boost.Python`: http://www.boost.org/libs/python/doc/index.html
.. _`SourceForge`: http://sourceforge.net/index.php
.. _`Docutils`: http://docutils.sourceforge.net
.. _`Python`: http://www.python.org
.. _`GCC-XML`: http://www.gccxml.org
.. _`Boost Software License`: http://boost.org/more/license_info.html
.. _`Parser package` : ../parser.png
.. _`ReleaseForge` : http://releaseforge.sourceforge.net
.. _`boost.type_traits` : http://www.boost.org/libs/type_traits/index.html
.. _`elementtree` : http://effbot.org/
