Understanding the Elusive FreeCADGui Module

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!
Post Reply
User avatar
derek-v-s
Posts: 26
Joined: Mon May 06, 2019 9:47 pm
Contact:

Understanding the Elusive FreeCADGui Module

Post by derek-v-s »

What is FreeCADGui (i.e. "import FreeCADGui")? Where is it defined?

From Gui/Application.cpp

Code: Select all

        PyDoc_STRVAR(FreeCADGui_doc,
            "The functions in the FreeCADGui module allow working with GUI documents,\n"
            "view providers, views, workbenches and much more.\n\n"
            "The FreeCADGui instance provides a list of references of GUI documents which\n"
            "can be addressed by a string. These documents contain the view providers for\n"
            "objects in the associated App document. An App and GUI document can be\n"
            "accessed with the same name.\n\n"
            "The FreeCADGui module also provides a set of functions to work with so called\n"
            "workbenches."
            );

#if PY_MAJOR_VERSION >= 3
        // if this returns a valid pointer then the 'FreeCADGui' Python module was loaded,
        // otherwise the executable was launched
        PyObject* modules = PyImport_GetModuleDict();
        PyObject* module = PyDict_GetItemString(modules, "FreeCADGui");
        if (!module) {
            static struct PyModuleDef FreeCADGuiModuleDef = {
                PyModuleDef_HEAD_INIT,
                "FreeCADGui", FreeCADGui_doc, -1,
                Application::Methods,
                NULL, NULL, NULL, NULL
            };
            module = PyModule_Create(&FreeCADGuiModuleDef);

            PyDict_SetItemString(modules, "FreeCADGui", module);
        }
        else {
            // extend the method list
            PyModule_AddFunctions(module, Application::Methods);
}
The "if (!module)" block above is the closest thing I can find; however, I'm confused about the preceding lines, that seem to imply it could have been defined and loaded previously.

Code: Select all

        // if this returns a valid pointer then the 'FreeCADGui' Python module was loaded,
        // otherwise the executable was launched
        PyObject* modules = PyImport_GetModuleDict();
        PyObject* module = PyDict_GetItemString(modules, "FreeCADGui");
I can't find a Python module called FreeCADGui, and I'm not sure what "the executable" is referring to.

The only other thing I can find is in Main/CMakeLists.txt

Code: Select all

    SET(FreeCADGuiPy_SRCS
        FreeCADGuiPy.cpp
    )

    add_library(FreeCADGuiPy SHARED ${FreeCADGuiPy_SRCS})

    target_link_libraries(FreeCADGuiPy FreeCADGui)

    SET_BIN_DIR(FreeCADGuiPy FreeCADGui)
SET_PYTHON_PREFIX_SUFFIX(FreeCADGuiPy)
Does that mean FreeCADGuiPy.cpp is being used to define "FreeCADGui"?
Last edited by derek-v-s on Fri May 17, 2019 9:33 pm, edited 1 time in total.
vocx
Veteran
Posts: 5197
Joined: Thu Oct 18, 2018 9:18 pm

Re: FreeCADGui

Post by vocx »

derek-v-s wrote: Thu May 16, 2019 10:36 pm ...

Does that mean FreeCADGuiPy.cpp is being used to define "FreeCADGui"?
That seems to be the case. See this: 3.FreeCAD Base and App module.md. Go to the end.

Since you seem to be going into the internals of FreeCAD, I suggest you check the developer documentation written by Qinfeng. He was the main developer of the Cfd workbench, which later on was forked and became the newer CfdOF workbench.

Since he saw the complexity of FreeCAD, he decided to write a "developer's book" in order to document the process of extending FreeCAD. He wrote such book mainly during his time working on the original Cfd workbench, so what he describes is the code in FreeCAD 0.16 and 0.17. This internal core probably hasn't change much since then, so the book should still be relevant.

The book is hosted in Github as he wanted the community to keep the book updated by providing pull requests with new content to the chapters.

https://github.com/qingfengxia/FreeCAD_Mod_Dev_Guide

However, I don't think the book has been updated in years. Qinfeng himself seems to be busy with his own job, so he rarely posts nowadays. Last time I saw, he contributed a few things to the FEM workbench and his own Cfd, just to keep the project working with a recent FreeCAD release. update on FreeCAD + OpenFOAM fluid dynamic computation

The FreeCAD codebase is complex, and only a small amount of users really know how the base system work. If you really want to become a FreeCAD hacker, maybe you'd like to see what can be updated in that book and also contribute better content to the Developer hub in the wiki.
Always add the important information to your posts if you need help. Also see Tutorials and Video tutorials.
To support the documentation effort, and code development, your donation is appreciated: liberapay.com/FreeCAD.
User avatar
derek-v-s
Posts: 26
Joined: Mon May 06, 2019 9:47 pm
Contact:

Re: FreeCADGui

Post by derek-v-s »

Thanks vocx. :-]

Code: Select all

// if this returns a valid pointer then the 'FreeCADGui' Python module was loaded,
// otherwise the executable was launched
I'm now interpreting this as

Code: Select all

// if this returns a valid pointer, then "import FreeCADGui" was used while running FreeCAD in console mode;
// otherwise, FreeCAD was launched as a GUI application
Is that correct?
User avatar
derek-v-s
Posts: 26
Joined: Mon May 06, 2019 9:47 pm
Contact:

Re: FreeCADGui

Post by derek-v-s »

Regarding "PyMOD_INIT_FUNC(FreeCADGui)" in FreeCADGuiPy.cpp

Code: Select all

/** Macro for initialization function of Python modules. 
 */
#if PY_MAJOR_VERSION >= 3
# define PyMOD_INIT_FUNC(name) PyMODINIT_FUNC PyInit_##name(void)
#else
# define PyMOD_INIT_FUNC(name) PyMODINIT_FUNC init##name(void)
#endif
-> https://github.com/FreeCAD/FreeCAD/blob ... Base.h#L93
--> https://docs.python.org/3/extending/ext ... n-function
vocx
Veteran
Posts: 5197
Joined: Thu Oct 18, 2018 9:18 pm

Re: FreeCADGui

Post by vocx »

derek-v-s wrote: Fri May 17, 2019 6:45 am

Code: Select all

// if this returns a valid pointer, then "import FreeCADGui" was used while running FreeCAD in console mode;
// otherwise, FreeCAD was launched as a GUI application
Is that correct?
I really don't know.

I interpret that as

Code: Select all

// if this returns a valid pointer then FreeCAD was launched as a GUI application
// otherwise, it was ran from the command line, that is, by running "freecadcmd" in the terminal
What is the "executable"? I don't know but I feel it should be one of freecad or freecadcmd.

I really can't tell. I'm not an expert on this. Hopefully Werner, one of the main developers, joins the conversation.
Always add the important information to your posts if you need help. Also see Tutorials and Video tutorials.
To support the documentation effort, and code development, your donation is appreciated: liberapay.com/FreeCAD.
User avatar
Kunda1
Veteran
Posts: 13434
Joined: Thu Jan 05, 2017 9:03 pm

Re: FreeCADGui

Post by Kunda1 »

Great thread and undertaking!
Perhaps change the title of this thread to get more exposure? Something like
'FreeCADGui - Help me decipher this so I can right documentation for it' :D
'Writing documentation for FreeCADGui - Need advice' etc...
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
wmayer
Founder
Posts: 20309
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: FreeCADGui

Post by wmayer »

What is FreeCADGui (i.e. "import FreeCADGui")? Where is it defined?
There are actually two locations where the FreeCADGui Python module is defined.

With the C-API of Python it's possible to create built-in modules which don't correspond to a physical file. In Py3 the function is PyModule_Create and in Py2 it's Py_InitModule3 (see Application.cpp) and the functions expect an argument that holds a list of static C/C++ functions. They are all defined in ApplicationPy.cpp.

When you just run the FreeCAD executable then the above approach is used to create the FreeCADGui Python module on-the-fly.
If you type FreeCADGui into the Python console then it shows <module 'FreeCADGui'> for Py3 or <module 'FreeCADGui' (built-in)> for Py2.

Then the second definition of the module is a physical file FreeCADGui.pyd (Windows) or FreeCADGui.so (Linux or macOS).
There are many people who use FreeCAD from the command line version (FreeCADCmd) or use it as a Python module in their own scripts and sometimes they also need access to the GUI and therefore can use FreeCADGui.pyd/FreeCADGui.so. The C++ code behind is indeed inside FreeCADGuiPy.cpp.

So, when doing an "import FreeCADGui" it loads the above file and when again writing FreeCADGui it now shows you which physical file has been loaded, e.g: <module 'FreeCADGui' from 'C:\\FreeCAD\\bin\\FreeCADGui.pyd'>
At this point the FreeCADGui module only offers a few functions and in order to use it you must call showMainWindow or setupWithoutGUI. Internally it also goes through the code in Application.cpp and adds the functions to the already existing module.
For Py2 you just use Py_InitModule3 like before but for Py3 it's slightly different. For an existing module the function PyModule_AddFunctions must be used, hence the check for "!module".
User avatar
derek-v-s
Posts: 26
Joined: Mon May 06, 2019 9:47 pm
Contact:

Re: FreeCADGui

Post by derek-v-s »

Hi wmayer :-]
Thanks for the explanation, and all the effort you have put into this project!

Does ApplicationPy.cpp exist simply to reduce the size of Application.cpp and organize the code?
Post Reply