From aa7aa6472446238f6945b64c8b55cd31af761e52 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 21 Jan 2016 14:49:57 +0100 Subject: [PATCH] + simplify porting of Drawing module to Python3 --- src/Mod/Drawing/App/AppDrawing.cpp | 14 +- src/Mod/Drawing/App/AppDrawingPy.cpp | 233 ++++++++++++++---------- src/Mod/Drawing/Gui/AppDrawingGui.cpp | 12 +- src/Mod/Drawing/Gui/AppDrawingGuiPy.cpp | 140 +++++++------- 4 files changed, 222 insertions(+), 177 deletions(-) diff --git a/src/Mod/Drawing/App/AppDrawing.cpp b/src/Mod/Drawing/App/AppDrawing.cpp index 9e0203a1c..915064a3a 100644 --- a/src/Mod/Drawing/App/AppDrawing.cpp +++ b/src/Mod/Drawing/App/AppDrawing.cpp @@ -27,15 +27,13 @@ #include "FeatureClip.h" #include "PageGroup.h" -extern struct PyMethodDef Drawing_methods[]; - -PyDoc_STRVAR(module_drawing_doc, -"This module is the drawing module."); +namespace Drawing { +extern PyObject* initModule(); +} /* Python entry */ -extern "C" { -void DrawingExport initDrawing() +PyMODINIT_FUNC initDrawing() { // load dependent module try { @@ -46,7 +44,7 @@ void DrawingExport initDrawing() PyErr_SetString(PyExc_ImportError, e.what()); return; } - Py_InitModule3("Drawing", Drawing_methods, module_drawing_doc); /* mod name, table ptr */ + (void)Drawing::initModule(); Base::Console().Log("Loading Drawing module... done\n"); @@ -66,5 +64,3 @@ void DrawingExport initDrawing() Drawing::FeatureClip ::init(); Drawing::FeatureViewSpreadsheet ::init(); } - -} // extern "C" diff --git a/src/Mod/Drawing/App/AppDrawingPy.cpp b/src/Mod/Drawing/App/AppDrawingPy.cpp index 6341d2861..d02e90ba6 100644 --- a/src/Mod/Drawing/App/AppDrawingPy.cpp +++ b/src/Mod/Drawing/App/AppDrawingPy.cpp @@ -26,6 +26,9 @@ # include #endif +#include +#include + #include #include "ProjectionAlgos.h" #include @@ -34,21 +37,84 @@ #include -using namespace Drawing; -using namespace Part; -using namespace std; +using Part::TopoShapePy; +using Part::TopoShape; -static PyObject * -project(PyObject *self, PyObject *args) +namespace Drawing { +class Module : public Py::ExtensionModule { - PyObject *pcObjShape; - PyObject *pcObjDir=0; +public: + Module() : Py::ExtensionModule("Drawing") + { + add_varargs_method("project",&Module::project, + "[visiblyG0,visiblyG1,hiddenG0,hiddenG1] = project(TopoShape[,App.Vector Direction, string type])\n" + " -- Project a shape and return the visible/invisible parts of it." + ); + add_varargs_method("projectEx",&Module::projectEx, + "[V,V1,VN,VO,VI,H,H1,HN,HO,HI] = projectEx(TopoShape[,App.Vector Direction, string type])\n" + " -- Project a shape and return the all parts of it." + ); + add_varargs_method("projectToSVG",&Module::projectToSVG, + "string = projectToSVG(TopoShape[,App.Vector Direction, string type])\n" + " -- Project a shape and return the SVG representation as string." + ); + add_varargs_method("projectToDXF",&Module::projectToDXF, + "string = projectToDXF(TopoShape[,App.Vector Direction, string type])\n" + " -- Project a shape and return the DXF representation as string." + ); + add_varargs_method("removeSvgTags",&Module::removeSvgTags, + "string = removeSvgTags(string) -- Removes the opening and closing svg tags\n" + "and other metatags from a svg code, making it embeddable" + ); + initialize("This module is the Drawing module."); // register with Python + } - if (!PyArg_ParseTuple(args, "O!|O!", &(TopoShapePy::Type), &pcObjShape,&(Base::VectorPy::Type), &pcObjDir)) // convert args: Python->C - return NULL; // NULL triggers exception + virtual ~Module() {} - PY_TRY { - TopoShapePy* pShape = static_cast(pcObjShape); +private: + virtual Py::Object invoke_method_varargs(void *method_def, const Py::Tuple &args) + { + try { + return Py::ExtensionModule::invoke_method_varargs(method_def, args); + } + catch (const Standard_Failure &e) { + std::string str; + Standard_CString msg = e.GetMessageString(); + str += typeid(e).name(); + str += " "; + if (msg) {str += msg;} + else {str += "No OCCT Exception Message";} + Base::Console().Error("%s\n", str.c_str()); + throw Py::Exception(Part::PartExceptionOCCError, str); + } + catch (const Base::Exception &e) { + std::string str; + str += "FreeCAD exception thrown ("; + str += e.what(); + str += ")"; + e.ReportException(); + throw Py::RuntimeError(str); + } + catch (const std::exception &e) { + std::string str; + str += "C++ exception thrown ("; + str += e.what(); + str += ")"; + Base::Console().Error("%s\n", str.c_str()); + throw Py::RuntimeError(str); + } + } + Py::Object project(const Py::Tuple& args) + { + PyObject *pcObjShape; + PyObject *pcObjDir=0; + + if (!PyArg_ParseTuple(args.ptr(), "O!|O!", + &(Part::TopoShapePy::Type), &pcObjShape, + &(Base::VectorPy::Type), &pcObjDir)) + throw Py::Exception(); + + Part::TopoShapePy* pShape = static_cast(pcObjShape); Base::Vector3d Vector(0,0,1); if (pcObjDir) Vector = *static_cast(pcObjDir)->getVectorPtr(); @@ -56,27 +122,23 @@ project(PyObject *self, PyObject *args) ProjectionAlgos Alg(pShape->getTopoShapePtr()->_Shape,Vector); Py::List list; - list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.V)) , true)); - list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.V1)), true)); - list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.H)) , true)); - list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.H1)), true)); + list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.V)) , true)); + list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.V1)), true)); + list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.H)) , true)); + list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.H1)), true)); - return Py::new_reference_to(list); + return list; + } + Py::Object projectEx(const Py::Tuple& args) + { + PyObject *pcObjShape; + PyObject *pcObjDir=0; - } PY_CATCH_OCC; + if (!PyArg_ParseTuple(args.ptr(), "O!|O!", + &(TopoShapePy::Type), &pcObjShape, + &(Base::VectorPy::Type), &pcObjDir)) + throw Py::Exception(); -} - -static PyObject * -projectEx(PyObject *self, PyObject *args) -{ - PyObject *pcObjShape; - PyObject *pcObjDir=0; - - if (!PyArg_ParseTuple(args, "O!|O!", &(TopoShapePy::Type), &pcObjShape,&(Base::VectorPy::Type), &pcObjDir)) // convert args: Python->C - return NULL; // NULL triggers exception - - PY_TRY { TopoShapePy* pShape = static_cast(pcObjShape); Base::Vector3d Vector(0,0,1); if (pcObjDir) @@ -96,25 +158,21 @@ projectEx(PyObject *self, PyObject *args) list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.HO)), true)); list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.HI)), true)); - return Py::new_reference_to(list); + return list; + } + Py::Object projectToSVG(const Py::Tuple& args) + { + PyObject *pcObjShape; + PyObject *pcObjDir=0; + const char *type=0; + float scale=1.0f; + float tol=0.1f; - } PY_CATCH_OCC; -} + if (!PyArg_ParseTuple(args.ptr(), "O!|O!sff", + &(TopoShapePy::Type), &pcObjShape, + &(Base::VectorPy::Type), &pcObjDir, &type, &scale, &tol)) + throw Py::Exception(); -static PyObject * -projectToSVG(PyObject *self, PyObject *args) -{ - PyObject *pcObjShape; - PyObject *pcObjDir=0; - const char *type=0; - float scale=1.0f; - float tol=0.1f; - - if (!PyArg_ParseTuple(args, "O!|O!sff", &(TopoShapePy::Type), &pcObjShape, - &(Base::VectorPy::Type), &pcObjDir, &type, &scale, &tol)) - return NULL; - - PY_TRY { TopoShapePy* pShape = static_cast(pcObjShape); Base::Vector3d Vector(0,0,1); if (pcObjDir) @@ -126,25 +184,21 @@ projectToSVG(PyObject *self, PyObject *args) hidden = true; Py::String result(Alg.getSVG(hidden?ProjectionAlgos::WithHidden:ProjectionAlgos::Plain, scale, tol)); - return Py::new_reference_to(result); + return result; + } + Py::Object projectToDXF(const Py::Tuple& args) + { + PyObject *pcObjShape; + PyObject *pcObjDir=0; + const char *type=0; + float scale=1.0f; + float tol=0.1f; - } PY_CATCH_OCC; -} + if (!PyArg_ParseTuple(args.ptr(), "O!|O!sff", + &(TopoShapePy::Type), &pcObjShape, + &(Base::VectorPy::Type), &pcObjDir, &type, &scale, &tol)) + throw Py::Exception(); -static PyObject * -projectToDXF(PyObject *self, PyObject *args) -{ - PyObject *pcObjShape; - PyObject *pcObjDir=0; - const char *type=0; - float scale=1.0f; - float tol=0.1f; - - if (!PyArg_ParseTuple(args, "O!|O!sff", &(TopoShapePy::Type), &pcObjShape, - &(Base::VectorPy::Type), &pcObjDir, &type, &scale, &tol)) - return NULL; - - PY_TRY { TopoShapePy* pShape = static_cast(pcObjShape); Base::Vector3d Vector(0,0,1); if (pcObjDir) @@ -156,23 +210,18 @@ projectToDXF(PyObject *self, PyObject *args) hidden = true; Py::String result(Alg.getDXF(hidden?ProjectionAlgos::WithHidden:ProjectionAlgos::Plain, scale, tol)); - return Py::new_reference_to(result); + return result; + } + Py::Object removeSvgTags(const Py::Tuple& args) + { + const char* svgcode; + if (!PyArg_ParseTuple(args.ptr(), "s",&svgcode)) + throw Py::Exception(); - } PY_CATCH_OCC; -} - -static PyObject * -removeSvgTags(PyObject *self, PyObject *args) -{ - const char* svgcode; - if (!PyArg_ParseTuple(args, "s",&svgcode)) - return NULL; - - PY_TRY { - string svg(svgcode); - string empty = ""; - string endline = "--endOfLine--"; - string linebreak = "\\n"; + std::string svg(svgcode); + std::string empty = ""; + std::string endline = "--endOfLine--"; + std::string linebreak = "\\n"; // removing linebreaks for regex to work boost::regex e1 ("\\n"); svg = boost::regex_replace(svg, e1, endline); @@ -195,23 +244,13 @@ removeSvgTags(PyObject *self, PyObject *args) boost::regex e7 ("--endOfLine--"); svg = boost::regex_replace(svg, e7, linebreak); Py::String result(svg); - return Py::new_reference_to(result); - } PY_CATCH_OCC; + return result; + } +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); } - - -/* registration table */ -struct PyMethodDef Drawing_methods[] = { - {"project" ,project ,METH_VARARGS, - "[visiblyG0,visiblyG1,hiddenG0,hiddenG1] = project(TopoShape[,App.Vector Direction, string type]) -- Project a shape and return the visible/invisible parts of it."}, - {"projectEx" ,projectEx ,METH_VARARGS, - "[V,V1,VN,VO,VI,H,H1,HN,HO,HI] = projectEx(TopoShape[,App.Vector Direction, string type]) -- Project a shape and return the all parts of it."}, - {"projectToSVG" ,projectToSVG ,METH_VARARGS, - "string = projectToSVG(TopoShape[,App.Vector Direction, string type]) -- Project a shape and return the SVG representation as string."}, - {"projectToDXF" ,projectToDXF ,METH_VARARGS, - "string = projectToDXF(TopoShape[,App.Vector Direction, string type]) -- Project a shape and return the DXF representation as string."}, - {"removeSvgTags" ,removeSvgTags ,METH_VARARGS, - "string = removeSvgTags(string) -- Removes the opening and closing svg tags and other metatags from a svg code, making it embeddable"}, - {NULL, NULL} /* end of table marker */ -}; +} // namespace Drawing diff --git a/src/Mod/Drawing/Gui/AppDrawingGui.cpp b/src/Mod/Drawing/Gui/AppDrawingGui.cpp index cf481d2c1..d45a89173 100644 --- a/src/Mod/Drawing/Gui/AppDrawingGui.cpp +++ b/src/Mod/Drawing/Gui/AppDrawingGui.cpp @@ -43,20 +43,20 @@ void loadDrawingResource() Gui::Translator::instance()->refresh(); } -/* registration table */ -extern struct PyMethodDef DrawingGui_Import_methods[]; +namespace DrawingGui { +extern PyObject* initModule(); +} /* Python entry */ -extern "C" { -void DrawingGuiExport initDrawingGui() +PyMODINIT_FUNC initDrawingGui() { if (!Gui::Application::Instance) { PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application."); return; } - (void) Py_InitModule("DrawingGui", DrawingGui_Import_methods); /* mod name, table ptr */ + (void) DrawingGui::initModule(); Base::Console().Log("Loading GUI of Drawing module... done\n"); // instantiating the commands @@ -71,5 +71,3 @@ void DrawingGuiExport initDrawingGui() // add resources and reloads the translators loadDrawingResource(); } - -} // extern "C" { diff --git a/src/Mod/Drawing/Gui/AppDrawingGuiPy.cpp b/src/Mod/Drawing/Gui/AppDrawingGuiPy.cpp index 1445cd0ab..f4e052fb2 100644 --- a/src/Mod/Drawing/Gui/AppDrawingGuiPy.cpp +++ b/src/Mod/Drawing/Gui/AppDrawingGuiPy.cpp @@ -28,6 +28,9 @@ # include #endif +#include +#include + #include "DrawingView.h" #include #include @@ -43,20 +46,45 @@ #include #include -using namespace DrawingGui; - - -/* module functions */ -static PyObject * -open(PyObject *self, PyObject *args) +namespace DrawingGui { +class Module : public Py::ExtensionModule { - char* Name; - if (!PyArg_ParseTuple(args, "et","utf-8",&Name)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); +public: + Module() : Py::ExtensionModule("DrawingGui") + { + add_varargs_method("open",&Module::open + ); + add_varargs_method("insert",&Module::importer + ); + add_varargs_method("export",&Module::exporter + ); + initialize("This module is the DrawingGui module."); // register with Python + } + + virtual ~Module() {} + +private: + virtual Py::Object invoke_method_varargs(void *method_def, const Py::Tuple &args) + { + try { + return Py::ExtensionModule::invoke_method_varargs(method_def, args); + } + catch (const Base::Exception &e) { + throw Py::RuntimeError(e.what()); + } + catch (const std::exception &e) { + throw Py::RuntimeError(e.what()); + } + } + Py::Object open(const Py::Tuple& args) + { + char* Name; + if (!PyArg_ParseTuple(args.ptr(), "et","utf-8",&Name)) + throw Py::Exception(); + + std::string EncodedName = std::string(Name); + PyMem_Free(Name); - PY_TRY { Base::FileInfo file(EncodedName.c_str()); if (file.hasExtension("svg") || file.hasExtension("svgz")) { QString fileName = QString::fromUtf8(EncodedName.c_str()); @@ -70,26 +98,21 @@ open(PyObject *self, PyObject *args) Gui::getMainWindow()->addWindow(view); } else { - PyErr_SetString(Base::BaseExceptionFreeCADError, "unknown filetype"); - return NULL; + throw Py::Exception(Base::BaseExceptionFreeCADError, "unknown filetype"); } - } PY_CATCH; - Py_Return; -} + return Py::None(); + } + Py::Object importer(const Py::Tuple& args) + { + char* Name; + const char* dummy; + if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&dummy)) + throw Py::Exception(); -/* module functions */ -static PyObject * -importer(PyObject *self, PyObject *args) -{ - char* Name; - const char* dummy; - if (!PyArg_ParseTuple(args, "et|s","utf-8",&Name,&dummy)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); + std::string EncodedName = std::string(Name); + PyMem_Free(Name); - PY_TRY { Base::FileInfo file(EncodedName.c_str()); if (file.hasExtension("svg") || file.hasExtension("svgz")) { QString fileName = QString::fromUtf8(EncodedName.c_str()); @@ -102,25 +125,21 @@ importer(PyObject *self, PyObject *args) view->resize( 400, 300 ); Gui::getMainWindow()->addWindow(view); } else { - PyErr_SetString(Base::BaseExceptionFreeCADError, "unknown filetype"); - return NULL; + throw Py::Exception(Base::BaseExceptionFreeCADError, "unknown filetype"); } - } PY_CATCH; - Py_Return; -} + return Py::None(); + } + Py::Object exporter(const Py::Tuple& args) + { + PyObject* object; + char* Name; + if (!PyArg_ParseTuple(args.ptr(), "Oet",&object,"utf-8",&Name)) + throw Py::Exception(); -static PyObject * -exporter(PyObject *self, PyObject *args) -{ - PyObject* object; - char* Name; - if (!PyArg_ParseTuple(args, "Oet",&object,"utf-8",&Name)) - return NULL; - std::string EncodedName = std::string(Name); - PyMem_Free(Name); + std::string EncodedName = std::string(Name); + PyMem_Free(Name); - PY_TRY { Py::Sequence list(object); for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { PyObject* item = (*it).ptr(); @@ -132,8 +151,7 @@ exporter(PyObject *self, PyObject *args) if (!str_out) { std::stringstream str; str << "Cannot open file '" << EncodedName << "' for writing"; - PyErr_SetString(PyExc_IOError, str.str().c_str()); - return NULL; + throw Py::Exception(PyExc_IOError, str.str().c_str()); } if (fi_out.hasExtension("svg")) { std::string fn = static_cast(obj)->PageResult.getValue(); @@ -142,8 +160,7 @@ exporter(PyObject *self, PyObject *args) if (!str_in) { std::stringstream str; str << "Cannot open file '" << fn << "' for reading"; - PyErr_SetString(PyExc_IOError, str.str().c_str()); - return NULL; + throw Py::Exception(PyExc_IOError, str.str().c_str()); } str_in >> str_out.rdbuf(); @@ -159,12 +176,10 @@ exporter(PyObject *self, PyObject *args) std::string viewName = view->Label.getValue(); App::DocumentObject* link = view->Source.getValue(); if (!link) { - PyErr_SetString(Base::BaseExceptionFreeCADError, "No object linked"); - return 0; + throw Py::Exception(Base::BaseExceptionFreeCADError, "No object linked"); } if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { - PyErr_SetString(PyExc_TypeError, "Linked object is not a Part object"); - return 0; + throw Py::TypeError("Linked object is not a Part object"); } TopoDS_Shape shape = static_cast(link)->Shape.getShape()._Shape; if (!shape.IsNull()) { @@ -187,25 +202,22 @@ exporter(PyObject *self, PyObject *args) break; } else { - PyErr_SetString(PyExc_TypeError, "Export of page object as this file format is not supported by Drawing module"); - return 0; + throw Py::TypeError("Export of page object as this file format is not supported by Drawing module"); } } else { - PyErr_SetString(PyExc_TypeError, "Export of this object type is not supported by Drawing module"); - return 0; + throw Py::TypeError("Export of this object type is not supported by Drawing module"); } } } - } PY_CATCH; - Py_Return; + return Py::None(); + } +}; + +PyObject* initModule() +{ + return (new Module)->module().ptr(); } -/* registration table */ -struct PyMethodDef DrawingGui_Import_methods[] = { - {"open" ,open , METH_VARARGS}, /* method name, C func ptr, always-tuple */ - {"insert" ,importer, METH_VARARGS}, - {"export" ,exporter, METH_VARARGS}, - {NULL, NULL} /* end of table marker */ -}; +} // namespace DrawingGui