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

From FreeCAD Documentation
(Created page with "Edytuj odpowiedni plik {{FileName|CMakeLists.txt}}, aby dodać odniesienia do tych dwóch plików. Z pliku XML system kompilacji utworzy następnie: * {{incode|[YourClass]Py.cpp}} * {{incode|[YourClass]Py.h}}.")
(Created page with "Pełna lista specyfikatorów formatu znajduje się na stronie [https://docs.python.org/3/c-api/arg.html dokumentacja Python C API]. Należy pamiętać, że zdefiniowano również kilka powiązanych funkcji, które pozwalają na użycie słów kluczowych itp. Kompletny zestaw to:")
 
(18 intermediate revisions by the same user not shown)
Line 9: Line 9:
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)''.
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ć:
You must create:
* {{incode|[YourClass]Py.xml}}
* {{incode|[YourClass]Py.xml}}
* {{incode|[YourClass]PyImp.cpp}}
* {{incode|[YourClass]PyImp.cpp}}.


Edytuj odpowiedni plik {{FileName|CMakeLists.txt}}, aby dodać odniesienia do tych dwóch plików. Z pliku XML system kompilacji utworzy następnie:
Edytuj odpowiedni plik {{FileName|CMakeLists.txt}}, aby dodać odniesienia do tych dwóch plików. Z pliku XML system kompilacji utworzy następnie:
Line 17: Line 17:
* {{incode|[YourClass]Py.h}}.
* {{incode|[YourClass]Py.h}}.


<span id="Class_Description_XML_File"></span>
== Class Description XML File ==
==Opis klasy Plik XML==


The XML file {{incode|[YourClass]Py.xml}} 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|Python console]].
Plik XML {{incode|[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 [[Python_console/pl|konsoli FreeCAD]].


W tym przykładzie przyjrzymy się wrapperowi dla klasy Axis C++. Plik opisu XML zaczyna się od:
For this example, we will look at the wrapper for the Axis C++ class. The XML description file begins with:


{{Code|lang=xml|code=
{{Code|lang=xml|code=
Line 46: Line 47:
}}
}}


Po tej preambule podana jest lista metod i atrybutów. Format metody jest następujący:
Following this preamble, a list of methods and attributes is given. The format of a method is:


{{Code|lang=xml|code=
{{Code|lang=xml|code=
Line 59: Line 60:
}}
}}


Format atrybutu jest następujący:
The format of an attribute is:


{{Code|lang=xml|code=
{{Code|lang=xml|code=
Line 70: Line 71:
}}
}}


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++:
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:


{{Code|lang=cpp|code=
{{Code|lang=cpp|code=
Line 76: Line 77:
}}
}}


oraz:
and:


{{Code|lang=cpp|code=
{{Code|lang=cpp|code=
Line 82: 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.
Plik implementacji C++ {{incode|[YourClass]PyImp.cpp}} zapewnia "klej", który łączy ze sobą struktury C++ i Python, skutecznie tłumacząc z jednego języka na drugi. System FreeCAD C++-to-Python zapewnia szereg klas C++, które mapują się na odpowiadające im typy Pythona. Najbardziej podstawową z nich jest klasa {{incode|Py::Object}} - rzadko tworzona bezpośrednio, klasa ta stanowi podstawę drzewa dziedziczenia i jest używana jako typ zwracany dla każdej funkcji zwracającej dane z języka Python.


<span id="Include_Files"></span>
=== Include Files ===
===Dołączanie plików===


Twój plik implementacyjny C++ będzie zawierać następujące pliki:
Your C++ implementation file will include the following files:


{{Code|lang=cpp|code=
{{Code|lang=cpp|code=
Line 100: Line 103:
}}
}}


Oczywiście można dołączyć wszelkie inne nagłówki C++, których kod wymaga do działania.
Of course, you may include whatever other C++ headers your code requires to function as well.


=== Constructor ===
<span id="Constructor"></span>
===Konstruktor===


Twoja implementacja C++ musi zawierać definicję funkcji PyInit: na przykład dla wrappera klasy Axis jest to:
Your C++ implementation must contain the definition of the PyInit function: for example, for the Axis class wrapper, this is


{{Code|lang=cpp|code=
{{Code|lang=cpp|code=
Line 110: Line 114:
}}
}}


W ramach tej funkcji najprawdopodobniej będziesz musiał przeanalizować argumenty przychodzące do konstruktora: najważniejszą funkcją do tego celu jest dostarczona przez środowisko Python {{incode|PyArg_ParseTuple}}. Przyjmuje ona przekazaną listę argumentów, deskryptor oczekiwanych argumentów, które powinna przeanalizować, oraz informacje o typie i lokalizacje przechowywania przeanalizowanych wyników. Na przykład:
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 {{incode|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:


{{Code|lang=cpp|code=
{{Code|lang=cpp|code=
Line 123: Line 127:
}}
}}


For a complete list of format specifiers see [https://docs.python.org/3/c-api/arg.html Python C API documentation]. Note that several related functions are also defined which allow the use of keywords, etc. The complete set is:
Pełna lista specyfikatorów formatu znajduje się na stronie [https://docs.python.org/3/c-api/arg.html dokumentacja Python C API]. Należy pamiętać, że zdefiniowano również kilka powiązanych funkcji, które pozwalają na użycie słów kluczowych itp. Kompletny zestaw to:


{{Code|lang=cpp|code=
{{Code|lang=cpp|code=
Line 133: Line 137:
}}
}}


== Links ==
<span id="Links"></span>
==Odnośniki internetowe==


* [[Exposing_Cplusplus_to_Python|Exposing Cplusplus to Python]]
* [[Exposing_Cplusplus_to_Python|Udostępnianie Cplusplus w środowisku Python]]
* [https://github.com/FreeCAD/FreeCAD/commit/20b86e55b8dd1873f4c19e036d047528c9ff7f4e Commit 20b86e5, exposing OCC's precision methods to Python]
* [https://github.com/FreeCAD/FreeCAD/commit/20b86e55b8dd1873f4c19e036d047528c9ff7f4e Commit 20b86e5, eksponujący precyzyjne metody OCC w środowisku Python].





Latest revision as of 08:49, 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

Plik implementacji C++ [YourClass]PyImp.cpp zapewnia "klej", który łączy ze sobą struktury C++ i Python, skutecznie tłumacząc z jednego języka na drugi. System FreeCAD C++-to-Python zapewnia szereg klas C++, które mapują się na odpowiadające im typy Pythona. Najbardziej podstawową z nich jest klasa Py::Object - rzadko tworzona bezpośrednio, klasa ta stanowi podstawę drzewa dziedziczenia i jest używana jako typ zwracany dla każdej funkcji zwracającej dane z języka Python.

Dołączanie plików

Twój plik implementacyjny C++ będzie zawierać następujące pliki:

#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"

Oczywiście można dołączyć wszelkie inne nagłówki C++, których kod wymaga do działania.

Konstruktor

Twoja implementacja C++ musi zawierać definicję funkcji PyInit: na przykład dla wrappera klasy Axis jest to:

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

W ramach tej funkcji najprawdopodobniej będziesz musiał przeanalizować argumenty przychodzące do konstruktora: najważniejszą funkcją do tego celu jest dostarczona przez środowisko Python PyArg_ParseTuple. Przyjmuje ona przekazaną listę argumentów, deskryptor oczekiwanych argumentów, które powinna przeanalizować, oraz informacje o typie i lokalizacje przechowywania przeanalizowanych wyników. Na przykład:

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;
    }

Pełna lista specyfikatorów formatu znajduje się na stronie dokumentacja Python C API. Należy pamiętać, że zdefiniowano również kilka powiązanych funkcji, które pozwalają na użycie słów kluczowych itp. Kompletny zestaw to:

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);

Odnośniki internetowe