Wrapping a Cplusplus class in Python/pl

Background
FreeCAD uses a custom XML-based system to create the Python wrapper for a C++ class. To wrap a C++ class for use in Python, two files must be manually created, and two files are automatically generated by the CMake build system (in addition to the C++ header and implementation files for the class).

You must create:

Edit the appropriate file to add references to these two files. From the XML file, the build system will then create:

Class Description XML File
The XML file provides information about the functions and attributes that the Python class implements, as well as the user documentation for those items that displays in the FreeCAD Python console.

For this example, we will look at the wrapper for the Axis C++ class. The XML description file begins with:

And defines a direction and a position (base) in 3D space.

The following constructors are supported:
 * Axis -- empty constructor
 * Axis(Axis) -- copy constructor
 * Axis(Base, Direction) -- define position and direction

Following this preamble, a list of methods and attributes is given. The format of a method is:

The format of an attribute is:

For an attribute, if "ReadOnly" is false, you will provide both a getter and a setter function. If it is true, only a getter is allowed. In this case we will be required to provide two functions in the implementation C++ file:

and:

Implementation Cplusplus File
The implementation C++ file provides the "glue" that connects the C++ and Python structures together, effectively translating from one language to the other. The FreeCAD C++-to-Python system provides a number of C++ classes that map to their corresponding Python type. The most fundamental of these is the class -- rarely created directly, this class provides the base of the inheritance tree, and is used as the return type for any function that is returning Python data.

Include Files
Your C++ implementation file will include the following files:

Of course, you may include whatever other C++ headers your code requires to function as well.

Constructor
Your C++ implementation must contain the definition of the PyInit function: for example, for the Axis class wrapper, this is

Within this function you will most likely need to parse incoming arguments to the constructor: the most important function for this purpose is the Python-provided. It takes in the passed argument list, a descriptor for the expected arguments that it should parse, and type information and storage locations for the parsed results. For example:

For a complete list of format specifiers see Python C API documentation. Note that several related functions are also defined which allow the use of keywords, etc. The complete set is: