Orochimarufan / PythonQt

PythonQt fork featuring Qt 5.x and Python 3.x support and improved CMake build system
GNU Lesser General Public License v2.1
48 stars 20 forks source link

Building a Python module from PythonQt-scripted app? #9

Closed twardoch closed 9 years ago

twardoch commented 9 years ago

Is it possible to build a regular Python module from a C++ Qt app that has uses PythonQt? I'm not interested in GUI but instead in an ability to create a Python module that would run in a regular Python environment which would expose the same classes (or a aubset) to regular Python that are available in PythonQt within my Qt C++ app.

Orochimarufan commented 9 years ago

It might be possible, but PythonQt wasn't built to do it, see http://pythonqt.sourceforge.net/ frontpage. You might want to take a look at PyQt (respective SIP) and PySide (respective Shiboken) and see if they do what you want. They basically need you to write a description of a c++ class and then they can generate bindings, like the PythonQt generator does.

melven commented 9 years ago

So I'm still trying to understand what you want to achieve more precisely, let's try this step-by-step:

  1. Usually with PythonQt you compile a C++-Qt-application. This app then may run python code which interacts with the C++ app. Background: the app is linked with the python library and desired C++/Qt objects/classes have wrappers in python and vice versa.
  2. If you simply want to write C-functions that can be called from within python, you can use for example ctypes: e.g. built a shared library/DLL from your C-code, load it in python and call individual functions.
  3. More elaborated approaches for C++ mentioned by Oro above.
  4. I suppose you could theoretically combine 1. and 2.: You can build a dynamic library from your C++ PythonQt code and provide an additional initialization function. The latter can be called via ctypes. The initialization function should call PythonQt::init(PythonAlreadyInitialized). However in a first test with this I obtained segfaults in the Python-library calls inside PythonQt::init.
twardoch commented 9 years ago

So, my goal is the following: we're writing a complex Qt C++ GUI application which is able to open its own documents, allow the user to perform a large number of interactive GUI operations, and then of course save the documents and export them to some external formats. Within that app, we're using PythonQt to expose scripting abilities to the user, initially with just a small script editor component (QScintilla), where the user can write their code and run it. For that, we expose certain parts of our app's API to Python via PythonQt. Later on, we'd like to hook up Python scripting to more GUI elements, create some hooks/listeners etc.

That's all good for the GUI app. But for other types of users, we'd also like to create a library with Python bindings that would include a large subset of what's available in the GUI app. The users could deploy that library, say, on a web server, or as part of some larger Python apps. So for that, my library should expose, ideally, the same API to the "external" Python as my GUI app exposes to the "internal" Python with PythonQt. So that both kinds of users (of the GUI app and of the library) could use the same API when writing their code.

I realize that I can achieve both goals via separate paths (PythonQt for scripting inside GUI app and SIP for a library) but that of course would be impractical because most likely, the APIs would differ.

Orochimarufan commented 9 years ago

This is actually a very interesting question to which I unfortunately don't know the answer...

You might want to try to get PythonQt into a state where it can be used to build extensions? I have no Idea if you could adapt SIP/Shiboken the other way around, but getting PythonQt working seems doable.

Another approach would be to write on top of the Python C API directly, though I don't know how viable that is in your case.

twardoch commented 9 years ago

Many thanks!

It turns out that my developers will adopt a hybrid approach. A pure C++ library that is independent of Qt, has its own Python bindings (not PythonQt-based), can work GUI-less and offers a good subset of the overall functionality. That lib can work in pure Python.

The lib also used in the Qt app directly. The Qt app also uses PythonQt, where both the "pure" bindings are available (for the lib), and the PythonQt bindings for the rest of the app (including GUI access).

So, that's solved for me in the end. Many thanks for the time you spent thinking about it.