Python wrapping of DataStructure¶
Files structures¶
The definition of exposed methods of the DataStructure objects is included
into the libaster.so. The main file is
bibcxx/PythonBindings/LibAster.cxx that exports all symbols.
By convention, one file is created per derivated DataStructure object named
<DataStructure object>Interface.{h,cxx}.
Exported methods¶
Constructors¶
DataStructure objects must be wrapped by a std::shared_ptr.
The definition of the wrapper must reflect the inheritance of the underlying
C++ DataStructures. In the following example, Function is derivated
from BaseFunction. It is necessary to pass a Python Function
object where a generic BaseFunction is expected.
Note
The constructors of the underlying instance should not be available
to the final user. That’s why the definition should use py::no_init.
To allow the serialization of the DataStructure objects using the Python pickling mechanism, we need a constructor that accepts the Jeveux name. The final user must not call this constructor.
For the creation of the DataStructure from Python, we also need a default constructor (with or without any argument).
Note
These constructors are defined using factory functions by
templating initFactoryPtr.
Examples¶
In this simple example one defines a default constructor (without argument) and the constructor used during unpickling that accepts the Jeveux name:
void exportFunctionToPython( py::module_ &mod )
{
namespace py = pybind11;
...
py::class_< Function, Function::FunctionPtr, BaseFunction > (
mod, "Function" )
.def( "__init__", py::make_constructor(
&initFactoryPtr< Function >) )
.def( "__init__", py::make_constructor(
&initFactoryPtr< Function,
std::string >) )
.def( "setValues", &Function::setValues )
...
;
}
A more complex example where the constructor needs another object. So the
default constructor needs a pointer on a Model
and another that takes the Jeveux name and this pointer:
void exportElementaryCharacteristicsToPython( py::module_ &mod )
{
using namespace pybind11;
class_< ElementaryCharacteristics, ElementaryCharacteristics::ElementaryCharacteristicsPtr,
bases< DataStructure > > ( "ElementaryCharacteristics", no_init )
.def( "__init__", make_constructor(
&initFactoryPtr< ElementaryCharacteristics,
ModelPtr >) )
.def( "__init__", make_constructor(
&initFactoryPtr< ElementaryCharacteristics,
std::string,
ModelPtr >) )
;
};
Other methods¶
See Recommendations / howto for methods with default arguments.
Pickling support¶
See code_aster.Supervis.Serializer module for the serialization
management.
DataStructures usually delegate the serialization to their Python objects.
Constructors arguments defined by
__getinitargs__()implemented incode_aster.Objects.DataStructurefor most of the classes.Example:
ElementaryCharacteristicsdefines its own arguments.__getinitargs__()returns a tuple with two elements: the Jeveux object name and theModelthat are passed to the constructor.To restore the internal state of the object, subclasses should defined their own
__getstate__()and__setstate__()methods. This is done through a subclass ofInternalStateBuilder.Example:
AssemblyMatrixdoes not take itsDOFNumberingas argument in its constructor. So it is stored by thesave()method of itsInternalStateBuilderand restored by therestore()method.