Python
The Python module allows to execute Python source code. This can be standard Python as well as the classes included in the "c4d" and "maxon" module.
The module's API is defined in the python.framework as well as lib_py.h.
//---------------------------------------------------------------------------------------- // Executes the given Python code. // @param[in] sourceCode The source code to execute. // @param[in] doc The BaseDocument to set "doc" and "op". If no BaseDocument is set, "doc" and "op" will not be defined. // @return OK on success. //---------------------------------------------------------------------------------------- static maxon::Result<void> ExecutePythonScript( maxon::String & sourceCode, BaseDocument * doc) { iferr_scope ;
// check code if (sourceCode. IsEmpty ()) return maxon::IllegalArgumentError( MAXON_SOURCE_LOCATION );
// init script iferr (scope.Init( "Python Script" _s, sourceCode, maxon::ERRORHANDLING::PRINT , nullptr )) { const String errorMessage = "Error on Init()" _s; return maxon::UnknownError( MAXON_SOURCE_LOCATION , errorMessage); }
// only set "doc" and "op" if a BaseDocument is set. // another option would be to set both "doc" and "op" to None if (doc != nullptr ) { // set "doc" and "op" variables
// the new Python API from python.framework is compatible with the legacy Python API from lib_py.h. // here we temporarily create an old PythonLibrary instance because it can create a PyObject // from a BaseDocument and BaseObject PythonLibrary pyLib; auto * pyObjectDoc = pyLib.ReturnGeListNode(doc, false ); if (pyObjectDoc == nullptr ) return maxon::UnexpectedError( MAXON_SOURCE_LOCATION ); auto * pyDoc = reinterpret_cast< maxon::py::NativePyObject * > (pyObjectDoc); scope.Add( "doc" _s, maxon::Data (pyDoc)) iferr_return ; python.CPy_Decref(pyDoc); BaseObject * op = doc-> GetActiveObject (); auto * pyObjectOp = op ? pyLib.ReturnGeListNode(op, false ) : pyLib.ReturnPyNone(); if (pyObjectOp == nullptr ) return maxon::UnexpectedError( MAXON_SOURCE_LOCATION ); auto * pyOp = reinterpret_cast< maxon::py::NativePyObject * > (pyObjectOp); scope.Add( "op" _s, maxon::Data (pyOp)) iferr_return ; python.CPy_Decref(pyOp); }
// set __name__ = __main__ scope.Add( "__name__" _s, maxon::Data ( "__main__" _s)) iferr_return ;
// stop all current threads which are potentially modifying the current document, // since the active script might modify the currently active document StopAllThreads ();
// executes the script and returns when it got executed. // info: if the script causes an unexpected infinite loop, Execute() does not return // and there is no way to stop from the outside. iferr (scope.Execute()) { const String errorMessage = "Error on Execute()" _s; return maxon::UnknownError( MAXON_SOURCE_LOCATION , errorMessage); } return maxon::OK ; }