Wrapping a Cplusplus class in Python/pl: Difference between revisions

From FreeCAD Documentation
(Created page with "oraz:")
(Created page with "==Implementacja pliku Cplusplus==")
Line 83: Line 83:
}}
}}


<span id="Implementation_Cplusplus_File"></span>
== Implementation Cplusplus File ==
==Implementacja pliku Cplusplus==


The implementation C++ file {{incode|[YourClass]PyImp.cpp}} 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 {{incode|Py::Object}} 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.
The implementation C++ file {{incode|[YourClass]PyImp.cpp}} 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 {{incode|Py::Object}} 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.

Revision as of 06:35, 6 November 2023

Other languages:
Ten artykuł to jedynie zalążek. Prosimy o uzupełnienie wiedzy!

Kontekst

FreeCAD używa niestandardowego systemu opartego na XML do tworzenia opakowania Pythona dla klasy C++. Aby opakować klasę C++ do użytku w środowisku Python, należy ręcznie utworzyć dwa pliki, a dwa pliki są automatycznie generowane przez system kompilacji CMake (oprócz plików nagłówkowych i implementacyjnych C++ dla klasy).

Musisz utworzyć:

  • [YourClass]Py.xml
  • [YourClass]PyImp.cpp.

Edytuj odpowiedni plik CMakeLists.txt, aby dodać odniesienia do tych dwóch plików. Z pliku XML system kompilacji utworzy następnie:

  • [YourClass]Py.cpp
  • [YourClass]Py.h.

Opis klasy Plik XML

Plik XML [YourClass]Py.xml zawiera informacje o funkcjach i atrybutach, które implementuje klasa Python, a także dokumentację użytkownika dla tych elementów, która wyświetla się w konsoli FreeCAD.

W tym przykładzie przyjrzymy się wrapperowi dla klasy Axis C++. Plik opisu XML zaczyna się od:

<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
    <PythonExport
        Father="PyObjectBase"
        Name="AxisPy"
        Twin="Axis"
        TwinPointer="Axis"
        Include="Base/Axis.h"
        FatherInclude="Base/PyObjectBase.h"
        Namespace="Base"
        Constructor="true"
        Delete="true"
        FatherNamespace="Base">
    <Documentation>
        <Author Licence="LGPL" Name="Juergen Riegel" EMail="FreeCAD@juergen-riegel.net" />
        <UserDocu>User documentation here
        </UserDocu>
        <DeveloperDocu>Developer documentation here</DeveloperDocu>
    </Documentation>

Po tej preambule podana jest lista metod i atrybutów. Format metody jest następujący:

<Methode Name="move">
    <Documentation>
        <UserDocu>
        move(Vector)
        Move the axis base along the vector
        </UserDocu>
    </Documentation>
</Methode>

Format atrybutu jest następujący:

<Attribute Name="Direction" ReadOnly="false">
    <Documentation>
        <UserDocu>Direction vector of the Axis</UserDocu>
    </Documentation>
    <Parameter Name="Direction" Type="Object" />
</Attribute>

W przypadku atrybutu, jeśli "ReadOnly" ma wartość false, należy podać zarówno funkcję pobierającą, jak i ustawiającą. Jeśli natomiast ma wartość true, dozwolona jest tylko funkcja getter. W tym przypadku będziemy musieli dostarczyć dwie funkcje w pliku implementacji C++:

Py::Object AxisPy::getDirection(void) const

oraz:

void AxisPy::setDirection(Py::Object arg)

Implementacja pliku Cplusplus

The implementation C++ file [YourClass]PyImp.cpp 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 Py::Object 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:

#include "PreCompiled.h"

#include "[YourClass].h"

// Inclusion of the generated files (generated out of [YourClass]Py.xml)
#include "[YourClass]Py.h"
#include "[YourClass]Py.cpp"

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

int AxisPy::PyInit(PyObject* args, PyObject* /*kwd*/)

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 PyArg_ParseTuple. 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:

PyObject* d;
    if (PyArg_ParseTuple(args, "O!O", &(Base::VectorPy::Type), &o,
                                      &(Base::VectorPy::Type), &d)) {
        // NOTE: The first parameter defines the base (origin) and the second the direction.
        *getAxisPtr() = Base::Axis(static_cast<Base::VectorPy*>(o)->value(),
                                   static_cast<Base::VectorPy*>(d)->value());
        return 0;
    }

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:

PyAPI_FUNC(int) PyArg_Parse (PyObject *, const char *, ...);
PyAPI_FUNC(int) PyArg_ParseTuple (PyObject *, const char *, ...);
PyAPI_FUNC(int) PyArg_ParseTupleAndKeywords (PyObject *, PyObject *, const char *, char **, ...);
PyAPI_FUNC(int) PyArg_VaParse (PyObject *, const char *, va_list);
PyAPI_FUNC(int) PyArg_VaParseTupleAndKeywords (PyObject *, PyObject *, const char *, char **, va_list);

Links