Gui::Command::doCommand for App

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
bernd
Veteran
Posts: 12851
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland
Contact:

Gui::Command::doCommand for App

Post by bernd »

In Gui it is possible by Gui::Command::doCommand to execute some Python command inside C++. Is there some similar for App C++ classes or is it not possible by design?

bernd
wmayer
Founder
Posts: 20324
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Gui::Command::doCommand for App

Post by wmayer »

This is by design. The actual functionality of Command::doCommand() is to do the macro recording (which uses the class MacroManager that is part of the GUI) and pass the string to the Python interpreter to execute it.

However, the design decision was made at a time when Qt was a single library file and thus was only allowed to be used in the GUI. In the meantime Qt has been split into many library files and with some refactoring work one can move the class MacroManager into the App module.

If you are not interested in macro recording but just want to execute a string you can also directly use Base::Interpreter().runString
User avatar
bernd
Veteran
Posts: 12851
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland
Contact:

Re: Gui::Command::doCommand for App

Post by bernd »

thanks werner for explaining this.

wmayer wrote: Fri Nov 02, 2018 6:51 pm but just want to execute a string you can also directly use Base::Interpreter().runString
this is what I need
User avatar
bernd
Veteran
Posts: 12851
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland
Contact:

Re: Gui::Command::doCommand for App

Post by bernd »

Z88 FEM mesh export is written in Python. To export the mesh of 3D example from Start WB the following code can be used:
import feminout.importZ88Mesh
feminout.importZ88Mesh.write(App.ActiveDocument.Box_Mesh.FemMesh, '/tmp/mesh.z88')
all the file formats implemented in C++ are exported as follows:

Code: Select all

import Fem
App.ActiveDocument.Box_Mesh.FemMesh.write('/tmp/mesh.unv')
I would like to make it possible to use the later to export a z88 mesh. Here is what I have so far ...

https://github.com/berndhahnebach/FreeC ... 7287435683

The problem is, I need either an instanz of FemMesh in a variable in the interpreter or the object name FemMesh belongs to. Both is where I stuck in my C++

bernd
wmayer
Founder
Posts: 20324
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Gui::Command::doCommand for App

Post by wmayer »

all the file formats implemented in C++ are exported as follows:
The problem is, I need either an instanz of FemMesh in a variable in the interpreter or the object name FemMesh belongs to. Both is where I stuck in my C++
Here it's the reverse. You have the z88 export implemented in Python and want to call it in C++. Since in C++ you can create a local instance of FemMesh somewhere inside a function the Python world would not be affected by this and thus it's not possible to search for a Python object in its name space. With some tricks it will be possible to achieve it too but it may cause some side-effects and thus the better way is to use PyCXX instead.

Now in order to call the Python code inside the C++ function you have to use Python's C API or better the PyCXX API. Create an instance of FemMeshPy and assign the FemMesh data structure of it. Via the PyCXX API you can import the importZ88Mesh module and use its write method.

Some code snippets will follow...
wmayer
Founder
Posts: 20324
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Gui::Command::doCommand for App

Post by wmayer »

Try this:

Code: Select all

void FemMesh::writeZ88(const std::string &FileName) const
{
    PyObject* module = PyImport_ImportModule("feminout.importZ88Mesh");
    if (!module)
        return;
    try {
        Py::Module z88mod(module, true);
        Py::Object mesh = Py::asObject(new FemMeshPy(const_cast<FemMesh*>(this)));
        Py::Callable method(z88mod.getAttr("write"));
        Py::Tuple args(2);
        args.setItem(0, mesh);
        args.setItem(1, Py::String(FileName));
        method.apply(args);
    }
    catch (Py::Exception& e) {
        e.clear();
    }
}
I haven't tested the code.
User avatar
bernd
Veteran
Posts: 12851
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland
Contact:

Re: Gui::Command::doCommand for App

Post by bernd »

gave it a try, but got an error on compile ...

Code: Select all

[ 94%] Built target PartDesignGui
/home/hugo/Documents/dev/freecad/freecadbhb_dev/freecad/src/Mod/Fem/App/FemMesh.cpp: In member function ‘void Fem::FemMesh::writeZ88(const string&) const’:
/home/hugo/Documents/dev/freecad/freecadbhb_dev/freecad/src/Mod/Fem/App/FemMesh.cpp:1621:44: error: expected type-specifier before ‘FemMeshPy’
         Py::Object mesh = Py::asObject(new FemMeshPy(const_cast<FemMesh*>(this)));
                                            ^~~~~~~~~
src/Mod/Fem/App/CMakeFiles/Fem.dir/build.make:176: die Regel für Ziel „src/Mod/Fem/App/CMakeFiles/Fem.dir/FemMesh.cpp.o“ scheiterte
make[2]: *** [src/Mod/Fem/App/CMakeFiles/Fem.dir/FemMesh.cpp.o] Fehler 1
CMakeFiles/Makefile2:4683: die Regel für Ziel „src/Mod/Fem/App/CMakeFiles/Fem.dir/all“ scheiterte
make[1]: *** [src/Mod/Fem/App/CMakeFiles/Fem.dir/all] Fehler 2
Makefile:127: die Regel für Ziel „all“ scheiterte
make: *** [all] Fehler 2
hugo@ahorn:~/Documents/dev/freecad/freecadbhb_dev/build$ 


https://github.com/berndhahnebach/FreeC ... d267c70b1f
wmayer
Founder
Posts: 20324
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Gui::Command::doCommand for App

Post by wmayer »

#include <FemMeshPy.h>
User avatar
bernd
Veteran
Posts: 12851
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland
Contact:

Re: Gui::Command::doCommand for App

Post by bernd »

:D
User avatar
bernd
Veteran
Posts: 12851
Joined: Sun Sep 08, 2013 8:07 pm
Location: Zürich, Switzerland
Contact:

Re: Gui::Command::doCommand for App

Post by bernd »

Post Reply