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.
Related
I made a program in c++ (visual studio 2010) that looks for serial com ports and compares their friendly names with defined text. When there is a match that port is opened/connected and serial communication starts.
The program notifies the user when a com port is found, whether the connection was successful or not and if the data send was successful or not and other useful information. The program uses cout to notify the user.
I want to replace console output window with windows form but cant find much resources online on how to do this. To illustrate, I want this:
To become this:
I included form1.h and other files and tried replacing cout with below line but code is not compiling:
Form1::textBox1->Text = L" Text I want to display";
Can anyone explain how to use textBox1, or a tutorial for this?
"I included form1.h" - You can't just grab random files and hope it works. That is not how C++ works, or computers in general.
How then do you do something like this? The Standard Library provides std::cout and Visual Studio by default includes the Standard Library, so using it is fairly easy. But for graphics, you will need another library. I recommend Qt, if only because there are good tutorials for beginners.
So I finally did achieve the functionality I described above in my question and thought I should post my findings here.
To convert my code from console output to Windows Form I basically had to migrate from c++ to C++/cli.
holowczak.com has a great tutorial on how to get started with windows form (c++/cli) in visual studio.
Next if there is any busy looping(like infinite while-loop) in your c++ code then you would need to run that busy loop on a separate thread or the program can hang. Dr.Dobb's tutorial on how to create and mange threads in c++/cli, can help a lot.
Finally, if you need to access resources (such as textbox and other controls) of windows form from another thread then a thread-safe call has to be made. Microsoft's "HowTo:Make thread-safe call to windows Form controls" explains how the invoke method can be used for updating textbox from another thread.
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++.
I want to create an wxWidgets app that is loaded from a shared library. It should be added as a plugin to an already existing C application.
In the samples directory (/samples/dll) of wxWidgets i found the file "my_dll.cpp". It's exactly what i need. It is exclusively for windows though. I need to make a .so linux version of it.
So i rewrote everything winapi thread related with pthreads. I have never really done multithreading so there are probably lots of mistakes in the code but i am not able to find them.
Maybe someone can help.
the most relevant functions are:
void run_wx_gui_from_dll(const char *title)
and
void* MyAppLauncher(void* event)
here is a link to the samples file from wxWidgets that uses winapi threads http://pastebin.com/KhK4uiKZ
here is a link to the code that uses pthreads http://pastebin.com/QmsPqYs5
My pthread version only works correctly when i put a sleep at the end of run_wx_gui_from_dll.
Without the sleep CMD_SHOW_WINDOW won't open a new frame. Just nothing happens. I put puts("received show window command"); in void MyDllApp::OnShowWindow. The string is printed to stdout so i know that wxQueueEvent works.
But wxWidgets seems to block at wxFrame *f = new MyDllFrame
...
...
// Send a message to wx thread to show a new frame:
wxThreadEvent *event =
new wxThreadEvent(wxEVT_THREAD, CMD_SHOW_WINDOW);
event->SetString(title);
wxQueueEvent(wxApp::GetInstance(), event);
sleep(3);
}
The windows version does not need a sleep.
run_wx_gui_from_dll starts a new thread from which the wxWidgets event loop is called. It then needs to wait until wxWidgets is properly initialized until it can queue commands. That is why i used the pthread condition. The windows version does a similar thing.
I also don't know what wxCriticalSectionLocker does. I left it in there just in case. Maybe that's part of the problem.
One error I see in your code is that you must lock the mutex before launching the thread, otherwise it may signal its initialization before you started waiting for it. I'm not sure this explains your problem (in fact, it probably doesn't), but it would still be nice to fix it. And if the problem persists, I'm afraid you really need to debug it and see what's going on, i.e. which thread is doing what.
It's also definitively a pity that we can't just use wxThread here, it's pretty annoying to have to write platform-specific to initialize a platform-independent library. We really ought to add some wxInitializeInNewThread() or something like this... If, by chance, you'd be interested in contributing it, please don't hesitate to post to wx-dev mailing list.
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
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!