I have a simple task:
- I wrote a C++ function and need to call it from Python
I spent a lot of time to make this working but still doesn't understand what my mistake is. here is what i have so far:
https://github.com/FreeCAD/FreeCAD/pull/7300
I assume my mistake is somewhere in the file ViewProviderFemPostPipeline.cpp in the Python connection part at the end.
Could anybody give me a pointer how it is done in general? Maybe then I find my bug.
how to expose a C++ function to Python
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
Re: how to expose a C++ function to Python
- Register FemPostPipelinePython (i.e. Fem::FemPostPipelinePython::init())
- Register ViewProviderFemPostPipelinePython after ViewProviderFemPostPipeline
- Implement ViewProviderFemPostPipelinePython::getPyObject()
Instead of ViewProviderFemPostPipelinePython::getPyObject() you should re-implement ViewProviderFemPostPipeline::getPyObject() because you probably want to access this new method when you create an FemPostPipeline object.
Code: Select all
diff --git a/src/Mod/Fem/App/AppFem.cpp b/src/Mod/Fem/App/AppFem.cpp
index 9d4ed26626..a6aac4a389 100644
--- a/src/Mod/Fem/App/AppFem.cpp
+++ b/src/Mod/Fem/App/AppFem.cpp
@@ -177,6 +177,7 @@ PyMOD_INIT_FUNC(Fem)
#ifdef FC_USE_VTK
Fem::FemPostObject ::init();
Fem::FemPostPipeline ::init();
+ Fem::FemPostPipelinePython ::init();
Fem::FemPostFilter ::init();
Fem::FemPostClipFilter ::init();
Fem::FemPostCutFilter ::init();
diff --git a/src/Mod/Fem/Gui/AppFemGui.cpp b/src/Mod/Fem/Gui/AppFemGui.cpp
index ffad1a0876..30ef85f519 100644
--- a/src/Mod/Fem/Gui/AppFemGui.cpp
+++ b/src/Mod/Fem/Gui/AppFemGui.cpp
@@ -136,8 +136,6 @@ PyMOD_INIT_FUNC(FemGui)
FemGui::ViewProviderFemMeshShapeNetgen ::init();
FemGui::PropertyFemMeshItem ::init();
- FemGui::ViewProviderFemPostPipelinePython ::init();
-
FemGui::ViewProviderSetElements ::init();
FemGui::ViewProviderSetFaces ::init();
FemGui::ViewProviderSetGeometry ::init();
@@ -153,6 +151,7 @@ PyMOD_INIT_FUNC(FemGui)
#ifdef FC_USE_VTK
FemGui::ViewProviderFemPostObject ::init();
FemGui::ViewProviderFemPostPipeline ::init();
+ FemGui::ViewProviderFemPostPipelinePython ::init();
FemGui::ViewProviderFemPostClip ::init();
FemGui::ViewProviderFemPostCut ::init();
FemGui::ViewProviderFemPostDataAlongLine ::init();
diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp
index b8d893ec99..f1b7d7ca58 100644
--- a/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp
+++ b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp
@@ -26,6 +26,7 @@
#include <vtkPointData.h>
#endif
+#include <App/FeaturePythonPyImp.h>
#include <App/GroupExtension.h>
#include <Base/Console.h>
#include <Gui/Application.h>
@@ -173,6 +174,14 @@ namespace Gui
/// @cond DOXERR
PROPERTY_SOURCE_TEMPLATE(FemGui::ViewProviderFemPostPipelinePython, FemGui::ViewProviderFemPostPipeline)
/// @endcond
+template<> PyObject* FemGui::ViewProviderFemPostPipelinePython::getPyObject() {
+ if (!pyViewObject) {
+ // ref counter is set to 1
+ pyViewObject = new App::FeaturePythonPyT<FemGui::ViewProviderFemPostPipelinePy>(this);
+ }
+ pyViewObject->IncRef();
+ return pyViewObject;
+}
// explicit template instantiation
template class FemGuiExport ViewProviderPythonFeatureT<ViewProviderFemPostPipeline>;
Code: Select all
d = App.newDocument()
d.addObject("Fem::FemPostPipelinePython")
d.ActiveObject. # CRASH!
Stacktrace:
Code: Select all
Program received signal SIGSEGV, Segmentation fault.
#0 /lib/x86_64-linux-gnu/libc.so.6(+0x3ef10) [0x7f9dfb36bf10]
#1 0x7f9d825c23d9 in Fem::PropertyPostDataObject::getMemSize() const from /home/user/Projects/build_clang/Mod/Fem/Fem.so+0x19
#2 0x7f9e02dfd1d1 in App::PropertyContainer::getMemSize() const from /home/user/Projects/build_clang/lib/libFreeCADApp.so+0xe1
#3 0x7f9e01f8554c in Base::PersistencePy::getMemSize() const from /home/user/Projects/build_clang/lib/libFreeCADBase.so+0x2c
#4 0x7f9e01f84a9a in Base::PersistencePy::staticCallback_getMemSize(_object*, void*) from /home/user/Projects/build_clang/lib/libFreeCADBase.so+0xba
#5 /usr/lib/x86_64-linux-gnu/libpython3.6m.so.1.0(_PyObject_GenericGetAttrWithDict+0x7e) [0x7f9e011491ae]
#6 0x7f9e01f94be1 in Base::PyObjectBase::_getattr(char const*) from /home/user/Projects/build_clang/lib/libFreeCADBase.so+0x131
#7 0x7f9e01efeb7f in Base::BaseClassPy::_getattr(char const*) from /home/user/Projects/build_clang/lib/libFreeCADBase.so+0x28f
#8 0x7f9e01f859bf in Base::PersistencePy::_getattr(char const*) from /home/user/Projects/build_clang/lib/libFreeCADBase.so+0x28f
#9 0x7f9e02e0cdbf in App::PropertyContainerPy::_getattr(char const*) from /home/user/Projects/build_clang/lib/libFreeCADApp.so+0x28f
#10 0x7f9e02c7ab9f in App::ExtensionContainerPy::_getattr(char const*) from /home/user/Projects/build_clang/lib/libFreeCADApp.so+0x28f
#11 0x7f9e02ca7b3f in App::DocumentObjectPy::_getattr(char const*) from /home/user/Projects/build_clang/lib/libFreeCADApp.so+0x28f
#12 0x7f9e02d533a9 in App::FeaturePythonPyT<App::DocumentObjectPy>::_getattr(char const*) from /home/user/Projects/build_clang/lib/libFreeCADApp.so+0x1a9
#13 0x7f9e01f93db2 in Base::PyObjectBase::__getattro(_object*, _object*) from /home/user/Projects/build_clang/lib/libFreeCADBase.so+0x192
#14 /usr/lib/x86_64-linux-gnu/libpython3.6m.so.1.0(PyObject_GetAttrString+0x34) [0x7f9e01149c34]
#15 0x7f9e042beb2f in Py::Object::getAttr(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const from /home/user/Projects/build_clang/lib/libFreeCADGui.so+0x3f
#16 0x7f9e047d1fa1 in Gui::CallTipsList::extractTipsFromObject(Py::Object&, Py::List&, QMap<QString, Gui::CallTip>&) const from /home/user/Projects/build_clang/lib/libFreeCADGui.so+0x131
#17 0x7f9e047d14d9 in Gui::CallTipsList::extractTips(QString const&) const from /home/user/Projects/build_clang/lib/libFreeCADGui.so+0x10a9
#18 0x7f9e047d3855 in Gui::CallTipsList::showTips(QString const&) from /home/user/Projects/build_clang/lib/libFreeCADGui.so+0x685
#19 0x7f9e047e44bf in Gui::PythonConsole::keyPressEvent(QKeyEvent*) from /home/user/Projects/build_clang/lib/libFreeCADGui.so+0x7ff
- wandererfan
- Veteran
- Posts: 6317
- Joined: Tue Nov 06, 2012 5:42 pm
- Contact:
Re: how to expose a C++ function to Python
ViewProviderFemPostPipelinePy.xml is not right. ViewProviderFemPostPipeline inherits from ViewProviderFemPostObject,
but the xml says ViewProviderFemPostPipelinePy inherits from ViewProviderDocumentObjectPy. It should be:
Code: Select all
Father="ViewProviderFemPostObjectPy"
Name="ViewProviderFemPostPipelinePy"
Twin="ViewProviderFemPostPipeline"
TwinPointer="ViewProviderFemPostPipeline"
Include="Mod/Fem/Gui/ViewProviderFemPostPipeline.h"
Namespace="FemGui"
FatherInclude="Mod/Fem/Gui/ViewProviderFemPostObject.h"
FatherNamespace="FemGui"
Re: how to expose a C++ function to Python
The ViewProviderFemPostPipelinePy.xml is fine.ViewProviderFemPostPipelinePy.xml is not right. ViewProviderFemPostPipeline inherits from ViewProviderFemPostObject,
but the xml says ViewProviderFemPostPipelinePy inherits from ViewProviderDocumentObjectPy. It should be:
For each ViewProvider**** class we don't have to implement a corresponding ViewProvider***Py class but in most cases the ViewProviderDocumentObjectPy is sufficient. So, that's why it's correct that ViewProviderFemPostPipelinePy inherits from ViewProviderDocumentObjectPy. Besides this we don't even have a class ViewProviderFemPostObjectPy -- because we never needed it.
Re: how to expose a C++ function to Python
Alone you go faster. Together we go farther
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
Re: how to expose a C++ function to Python
Many thanks for all your help!
However, I did everything as suggested and this was the result:
https://github.com/FreeCAD/FreeCAD/pull ... af1b01706a
Sadly, this did not work. The I realized that the App part also does not have an ::init() of a python class. So I removed it to get App as it is in master and modified the Viewprovider part accordingly.
In effect I applied these changes:
https://github.com/FreeCAD/FreeCAD/pull ... 2ebe5346ee
And now it works!
It seems that i forgot to add to the Viewprovider a
function.
However, why is the type definition of a
not necessary. Following Werner's post, it was correct that I did this.
However, I did everything as suggested and this was the result:
https://github.com/FreeCAD/FreeCAD/pull ... af1b01706a
Sadly, this did not work. The I realized that the App part also does not have an ::init() of a python class. So I removed it to get App as it is in master and modified the Viewprovider part accordingly.
In effect I applied these changes:
https://github.com/FreeCAD/FreeCAD/pull ... 2ebe5346ee
And now it works!
It seems that i forgot to add to the Viewprovider a
Code: Select all
PyObject *getPyObject();
However, why is the type definition of a
Code: Select all
FemGui::ViewProviderFemPostPipelinePython