Adding a Qt GUI to a Dynamic Library - c++

Greetings overflowers.
I am trying to add a GUI to to an existing project. More specifically to a plugin that is loaded as a .so file (or when compiled on win32 a .dll)
The project has its own threading implementation already to deal with portability. I know that Qt has its own cross platform threading model but it would be preferable to stay within this existing threading model.
My question to the Qt veterans out there [I have only just started reading the docs] is: Would it be possible to embed a GUI using Qt in to a plugin as described above? The plugin already is a command line interface and I would like to have the GUI optional, even if its compiled in. Since those standard functions get called by the main program, the GUI (which I assume will live in another thread) will have to be accessible or able to have methods called on it so that the CLI thread can coexist and the standard functions can work with any permutation of the two interfaces.
edit 1:
after playing with the code a bit I am able to launch a simple GUI from the plugin. The plugin already is the CLI and has functions that are called from the main program. I simply created a new thread on initialization of the plugin and launched the blocking GUI from there:
QApplication app(NULL, NULL);
window = new zGui;
window->show();
app.exec();
The question here is: Is it possible to communicate with the GUI or rather access GUI elements from the CLI thread?
edit 2: some results
Alright, so far starting the blocking GUI in a separate thread has worked with no problems. I am able to access widgets in the GUI from the main plugin thread as well. I understand that this practice is discouraged as not only per the answers I've received so far but also the Qt libs are spitting out some warning about unsafe access by another thread.
As of now I have only been working in a linux environment, perhaps real issues will be presented on other systems. I have seen only one glitch that I can not say for sure is related:
Upon changing the the max and min values of a progress bar widget, the progress bar appears blank. I was able to apply a simple fix to this by the following
//here is me setting the values
window->progressBar->setMaximum(character.maxHP);
window->progressBar_2->setMaximum(character.maxMP);
window->progressBar->setValue(character.curHP);
window->progressBar_2->setValue(character.curMP);
//and here is the fix
window->progressBar->setVisible(false);
window->progressBar->setVisible(true);
window->progressBar_2->setVisible(false);
window->progressBar_2->setVisible(true);
I suppose my final question is 'What specifically are the situations where accessing a Qt GUI from an other thread is unsafe and why?'

You can use a Qt GUI from a dll or so that is called from a non-Qt application, but it cannot be from a secondary thread, it has to run in the main thread. And the application event loop is started via a blocking method that returns when the GUI is closed out, so if you needed to have logic running in your app that is independent of the GUI, then that logic would need to be running in a secondary thread.
If you felt ambitious, you could modify the QCoreApplication and QEventLoop classes in such a way that you can manage the event loop from your calling application, and it probably wouldn't be all that difficult. But as far as I know there's no way to do it with Qt out of the box.

Consideing to Gerald answer, might I suggest that its better to keep the CLI (your app) separate from your apps GUI (ergo, a separate app).
Make your GUI app use the cli in the background. its easily done by using QProcess.
cheers!

Related

How to create a single process but multithreads MFC GUI application with MPI?

All I need is just to write a simple MFC Windows application using MSMPI, but I don't want to launch multiple processes as my GUI application may need some user interaction before the multi-threading part. For instance, I'd like to create 2 threads after click a 'Run' button.
I have tried to run my program using the command line: mpiexec.exe -n 2 myprogram.exe but this will create two processes and I will see two application windows.
I have also tried the MPI cluster debugging option in Visual Studio 2010 but it creates two processes as well.
This seems to be a very basic question but I find it difficult to find an answer in Google.
Edit
To eliminate the confusion here, I have to clarify a few things:
I have a very complicated and large codebase that already uses MS-MPI to achieve parallelism and I have to build a MFC GUI on top of it. For this reason, I cannot use any other parallelism mechanism such as std::thread because that will mean I have to rewrite a lot of things which is not affordable.
From my understanding, to launch a MPI program, I have to run the external program called mpiexec.exe in Windows. I haven't figured out if it is possible to launch the program by its own and still achieve MPI features. I'm quite new to MPI. I'm not so sure if it is possible to achieve what I'm asking for. If it is not, I would be very appreciated if anyone can let me know why and possible workaround.
Simply put, I want to create a MFC GUI wrapper for a MPI enabled software and this has to be a multithreading program instead of multiple instances (processes) of this GUI wrapped program (e.g. running this program by mpiexec -n 2 xxx.exe will just create 2 instances of the same program)
I'm guessing you're creating some kind of graphical front-end for some MPI software you have. As far as I can see you have two options.
Option 1
Create a separate Win32 application (without MPI) that is your GUI, let this application run "mpiexec" or equivalent with the correct parameters to start the application when the user requests to.
Option 2
You need to make sure you only launch the GUI on one MPI instance. You do this by looking up the ID of the current program from MPI during startup and if it is 0, start the GUI.
Something like this:
int main(int argc, char** argv){
int myid;
...
MPI_Init(&argc, &argv);
...
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
if(myid == 0){
launchGui();
}else{
waitForAndProcessMessages();
}
...
MPI_Finalize();
return 0;
}
Obviously you still need to fill in all the bits an pieces to make MPI function as you normally would but in this example the first launched instance will become the GUI and not do any processing. Any instance that later joins the HPC will wait for messages and process them until they terminate.
I'd like to create 2 threads after click a 'Run' button"
Since, you have VS 2010, I am not sure of std::thread compatibility. You could use MFC's threading API as follows -
CWinThread* myThread = AfxBeginThread(myThreadFunc, &threadInfoStruct);
You can use PostThreadMessage API to relay information between various MFC threads, i.e. from GUI to Business logic, and thus into MPI threads and back.
Of course, if your compiler supports std::thread, that is the way to go.
Related to std::thread, often the most correct way to implement what you want is to use std::async. Read up about thread based programming vs task based programming in Effective Modern C++.

How to create a singleton Qt application on windows? [duplicate]

This question already has answers here:
Closed 10 years ago.
I wonder how to create an application that would be capable to have only one instance of it running on a host OS at a time.. so to say a singleton app. I wonder how to create such singleton C++ app in Qt?
You could use the QtSingleApplication class from Qt Solutions. Notice that this is not a standard Qt class. You should download it. The QtSingleApplication component provides support for applications
that can be only started once per user.
When the application starts, create a file. When the application ends, remove the file.
If the file exists, exit with an error message.
You don't really need Qt for this, it's a graphics library.
Just use some normal WINAPI method to do this.
You could either create files like suggested (but can get strange when your application will crash, or after a power outage), or use memory mapped files or some other global objects to check if your app is stil running.
You also could just check the process list to see if another copy is running.
Another thing is to do a FindWindow with your window class, that's pretty easy and will work well.
There are a lot of options, just search for this, it's a common question.
(you could use some libraries for this, but since you are only targetting windows, I'd go with FindWindow.)

Qt calling QApplication::exec from library

This is a follow on from a question I asked about embedding Qt code in a legacy C application.
I am able to build Qt code into my C application and was surprised to find that I can even run gui code from within the static library I'm using to do this.
(My C application is also GUI driven, by the way).
This opens up some exciting possibilities, and I'm trying to get the two GUIs to work side by side.
The problem I have now is that in order to launch Qt GUI code I need to call QApplication::exec(), which is effectively blocking the rest of my application as it doesn't return until I kill the qt gui.
Is there any way I can start the qt gui code up and still return to my host application?
I appreciate I could start my Qt code up as a different process and implement some inter process communication, but the whole point is to try and get this embedded as a library.
There's also no way I can host the legacy application in Qt, before anyone suggests that!
Thanks for your help!
Don't call QApplication::exec(). Instead have the application call QApplication::processEvents() in it's event loop.
The answer to your problem is threading.
Since you are doing C, pthreads is probably available to you.
void * qt_thread(void * parm) {
// code here
QApplication::exec();
}
//some where in your main()
pthread_t qt;
pthread_create(&qt, NULL, qt_thread, NULL); //returns immediately
// rest of code
This is a VERY rough example, you should study and learn threading properly.
Good reference:
https://computing.llnl.gov/tutorials/pthreads/
Well, you can start a second thread (e.g., using the pthread library) and start QApplication::exec() from the second thread. However, you must be very careful when communicating with your QT code in order not to have race conditions in your library.

how to connect two programs (c++,qt)

I have 2 programs. Console and QT. Console program should make some data , and qt program should than show this data. But this should be separate programs, and i do not know how can i tell QT program to do somthing from my Console. Two programs are local and Qt program is always running (so that i can not just run it every time), and Console is only lunched when needed. So the question is - how can i execute somthing in Qt after console program finishes?
P.S. The console program makes a file that Qt program can read and than display.
I'm using windows.
Int Qt, you can start the console process with QProcess. That class has a finished signal, which you can connect to a slot in your application object. Then, when the console process finishes, the finished signal fires, and your slot function is called. At that point you can read the output file.
This is more efficient than a QFileSystemWatcher because you're directly watching the relevant event (console program finishes).
You might consider using something like QFileSystemWatcher to poll for changes in a particular directory, then have your console program write the file there. That way the Qt program would get a notification when the contents of the directory change.
Interprocess Communication (IPC) is the solution you're looking for.
The MSDN documentation is available here, containing more details about implementing this in your application, as well as code samples.
This technique is called "Screen scraping". You are doing this by connecting console app's stdout to Qt apps input.
Look at http://doc.qt.nokia.com/latest/qprocess.html
Take a look at QSharedMemory: http://doc.qt.nokia.com/4.7-snapshot/qsharedmemory.html. It allows inter-thread and inter-process communication.
A very nice and short example on how to use QSharedMemory is here: http://doc.trolltech.com/main-snapshot/ipc-sharedmemory.html

What is a good way to add MFC gui to a Win32 C++ command line application?

We have a command line application that could benefit from a GUI. We want to add some plotting functionality and have identified a plotting library that uses MFC. Initially we developed a separate app, but we'd rather have the GUI in the same process space.
I was thinking of possibly a GUI in an MFC DLL that could be hosted in the production app AND in a testing app.
The questions are:
What are the steps necessary to add an MFC GUI to a win32 command line app
Is it possible to make a GUI in an MFC DLL and how can it be done? (so that different apps can reuse the same GUI)
EDIT
I should add that this is an unmanaged app (and needs to stay that way - it needs to be highly performant, makes extensive use of templates, boost, custom allocators, internally developed thread serialization, etc)
RESULTS:
Nick D's answer worked great - especially the follow-up link in his comment with the details about a regular MFC DLL.
Note that we will be using Qt for the next iteration. Modifying our build environment and getting used to a a new framework was just too much this time around.
You can call/reuse GUI code in a dll. (I even use Delphi forms in my C++ projects)
A very simple dll example:
// The DLL exports foo() function
void foo()
{
AFX_MANAGE_STATE( AfxGetStaticModuleState() );
CDlgFoo dlg;
dlg.DoModal();
}
In the console program you'll have code like this:
h = ::LoadLibrary( "my.dll" );
::DisableThreadLibraryCalls( h );
pfoo = (foo_type*)::GetProcAddress( h, (const char*)1 );
if ( pfoo ) pfoo();
First, you will have to surrender WinMain().
If you still want to retain the command-line arguments functionality, process command arguments in InitInstance() of your App class.
The straight forward approach would be to add a switch to your program and given a certain value it will launch the gui, otherwise use the command line options. Something like "app.exe -mode=gui". If you don't see this command arg on program launch, fall back to the old command line behavior.
Regarding the DLL, you could write all the UI functionality in a DLL and use it from your "production app" where you have a message loop running and a WinMain. But what's the point? If it's for testing purposes why not just separate the presentation from the logic and test the logic alone. How do you intend to test the UI in your test app anyway? Simulate button clicks?