Seite 1 von 1

concolen Programm mit gui erstellen

Verfasst: 8. April 2005 18:58
von december_soul
Folgendes Problem.
Ich habe ein Programm das im Grunde nur in der Console laufen soll.
Dazu habe ich also in kdevelop eine Consolen Application erstellt und implementiert.

Nun will ich aber zu testzwecken eine GUI schreiben damit man bei der Entwicklung mehr sehen kann.

Die gui soll man per schalter "-enable-gui" einschalten können.
Auch nur dann soll das Programm die libs suchen/bzw benötigen.
Das denke ich kann man ganz gut mit dem Precompilier lösen.

Die GUI soll im Grunde nur Sachen anzeigen können.
Dazu habe ich mir eine zwischenklasse geschrieben, die die GUI steuern soll.
(oder gibt es hier bessere ansätze?)
Nun habe ich aber ein Problem damit eine GUI mit qt zu erstellen, da ich ja nur eine Consolen Application erstellt habe.
Bis jetzt habe ich immer nur Testprogramme mit qt erstellt bei denen das ganze Programm auf gui angelegt ist.

Es gibt doch 1000 Progamme die Programm <-> GUI kommunikation machen.
Was ist dann sinnvoller, beides eigene Threads oder zwei unterschiedliche Programme die über einen kanal kommunizieren?

Ich will ja nur hin und wieder ein image dastellen.

Kannst mir da vielleicht jemand weiter helfen?
Ist mehr eine Grundsatzfrage.
Wobei ein richtiges Beispiel mir sicher viel weiter helfen würde.

Eine kleines beispiel Programm oder howto wäre nicht schlecht.

Verfasst: 10. April 2005 22:59
von lepsai
ich hätte ein GUI-Programm geschrieben. Die GUI muss man ja nicht anzeigen, wenn man nicht will. Aber ich hab' keine Probleme bei der Implementierung, brauche z.B. keine Interprozesskommunikation.
Wenn ich die Zwischenergebnise einer Verarbeitungsprozedur anzeigen möchte, dann ist das eine definitiv bessere Variante. Wenn du dein Vorhaben etwas präziser beschreibst, kann man dir vielleicht besser helfen.

Verfasst: 11. April 2005 09:42
von december_soul
Das Programm das ich schreibe ist und soll ein Console Programm bleiben.
(Wird später in ein anderes Projekt integriert auf dem es nichtmal X, geschweige denn qt gibt)

Ich habe mich nun schon drauf eingestellt einen eigenen Thread mit der gui zu erstellen.
Nun muß ich erstmal rausfinden wie ich eine gui ohne den Projektassistenten von kdevelop erstelle. Sehr hilfreich wäre es trotzdem wenn ich den qtdesigner verwenden könnte.

Ein weiteres Problem wird wohl die Threadkommunikation.
Aber das soll hier nicht dass Problem sein. (lese ich gerade)

Ich bin nur etwas verwundert das es kaum howtos zu dem Thema gibt.
Ist doch ein Problem das echt jeder 10. Linux Programmierer hat. (denke ich)

Ich habe z.B. gelesen das ich wenn ich qt mit threads verwenden möchte das ganze neu übersetzen muß. Bezieht sich das nur auf Threads innerhalb der gui oder auch auf meinen fall?

Verfasst: 11. April 2005 10:29
von lepsai
Mit Threads kommste überhaupt nicht weiter... wie soll man das einfach erklären? Wenn du Threads benutzt muss Qt zu deinem gesamten Programm gelinkt werden und das geht ja bei dir nicht. Wenn auf dem Zielrechner gar keine Qt installiert ist, ist es nicht gerade vorteilhaft. Was du brauchst, sind zwei Prozesse (QProcess), die miteinander kommunizieren können. Kommunikation erfolgt über sockets (QSocket, QServerSocket). Allerdings wirst du die Qt API bei deinem Konsolenprogramm nicht verwenden können, also muss die Socketfunktionalität durch Socket API der Standardbibliothek implementiert werden. Das alles ist nicht wirklich schön, aber in deinem Fall wahrscheinlich die einzige Lösung.

Verfasst: 11. April 2005 10:39
von Goos
Du solltest bei deinen Voraussetzungen wirklich nicht versuchen an ne Konsolenanwendung noch ne GUI ranzubasteln. Gib deine Debuginfos einfach ueber nen Socket oder ne Pipe raus und visualisier das dann mit ner separaten kleinen Application. Wenn du dein GUI allerdings spaeter nicht mehr brauchst, dann ists wahrscheinlich zuviel Aufwand. Ich kann eh nicht ganz nachvollziehen, weshalb dir Konsolenausgaben nicht reichen.
Koenntest vielleicht etwas naeher beschreiben was du tolles visualisieren willst, so dass auch mir die Erleuchtung kommt? :)

Goos

Verfasst: 11. April 2005 10:39
von december_soul
So ich versuche es nun nochmal etwas genauer zu beschreiben was mein Problem ist:

Also ich habe eine main. In der main soll ein Thread gestartet werden der die GUI darstellt.

Code: Alles auswählen

#include <iostream>
#include <cstdlib>

#include "bmidgl.h"
#include "threadapp.h"

using namespace std;

int main(int argc, char *argv[])
{

   std::cout << "Hello, world!" << std::endl;
  
  ThreadApp t;

  t.start(QThread::HighestPriority);

// Verhindert, dass das Programm zu früh beendet wird
  //mache was.........
  while (t.running())
  {}
  
  return EXIT_SUCCESS;
}
Header des Threads

Code: Alles auswählen

#include <iostream>
#include <string>

#include <qfile.h>
#include <qtextstream.h>
#include <qstring.h>

#include <qthread.h>

class ThreadApp: public QThread{
public:
    ThreadApp();

    ~ThreadApp();

    
        void run();
        void stop();

    private:
        bool stopped;
};
Implementation des Threads

Code: Alles auswählen

#include "threadapp.h"


ThreadApp::ThreadApp()
{
    this->stopped = false;
}


void ThreadApp::run()
{
    std::cout << "Thread is running..."<< std::endl;
}


void ThreadApp::stop()
{
    this->stopped = true;
}

Soweit erstmal dazu.
Später soll dann in dem Thread die richtige GUI rein.
Leider will das nicht mal so laufen.

Code: Alles auswählen

cd '/home/patrick/0_arbeit/gui4/debug' && WANT_AUTOCONF_2_5="1" WANT_AUTOMAKE_1_6="1" make -k 
make all-recursive
Making all in src
source='/home/patrick/0_arbeit/gui4/src/gui4.cpp' object='gui4.o' libtool=no depfile='.deps/gui4.Po' tmpdepfile='.deps/gui4.TPo' depmode=gcc3 /bin/sh /home/patrick/0_arbeit/gui4/depcomp g++ -DHAVE_CONFIG_H -I. -I/home/patrick/0_arbeit/gui4/src -I.. -I /usr/include/qt3/ -DQT_THREAD_SUPPORT -O0 -g3 -c -o gui4.o `test -f '/home/patrick/0_arbeit/gui4/src/gui4.cpp' || echo '/home/patrick/0_arbeit/gui4/src/'`/home/patrick/0_arbeit/gui4/src/gui4.cpp
source='/home/patrick/0_arbeit/gui4/src/threadapp.cpp' object='threadapp.o' libtool=no depfile='.deps/threadapp.Po' tmpdepfile='.deps/threadapp.TPo' depmode=gcc3 /bin/sh /home/patrick/0_arbeit/gui4/depcomp g++ -DHAVE_CONFIG_H -I. -I/home/patrick/0_arbeit/gui4/src -I.. -I /usr/include/qt3/ -DQT_THREAD_SUPPORT -O0 -g3 -c -o threadapp.o `test -f '/home/patrick/0_arbeit/gui4/src/threadapp.cpp' || echo '/home/patrick/0_arbeit/gui4/src/'`/home/patrick/0_arbeit/gui4/src/threadapp.cpp
/bin/sh ../libtool --mode=link g++ -DQT_THREAD_SUPPORT -O0 -g3 -o gui4 gui4.o bmidgl.o threadapp.o 
g++ -DQT_THREAD_SUPPORT -O0 -g3 -o gui4 gui4.o bmidgl.o threadapp.o 
gui4.o(.text+0x4f): In function `main':
/home/patrick/0_arbeit/gui4/src/gui4.cpp:41: undefined reference to `QThread::start(QThread::Priority)'
gui4.o(.text+0x5a):/home/patrick/0_arbeit/gui4/src/gui4.cpp:45: undefined reference to `QThread::running() const'
gui4.o(.text+0x69):/home/patrick/0_arbeit/gui4/src/gui4.cpp:48: undefined reference to `ThreadApp::~ThreadApp [in-charge]()'
...................................
1000 weitere Zeilen mit undefined reference to 
Sieht für mich ein wenig so aus als wenn Threads nicht aktiviert sind.
Dabei sieht man ja das folgende Zeilen vorhanden sind:
-I /usr/include/qt3/
-DQT_THREAD_SUPPORT

Ich habe auch
libqt3-mt
und
libqt3-mt-dev
installiert.

Verfasst: 11. April 2005 10:43
von december_soul
OK ich habe etwas zu langsam geschrieben.
Also mein Programm verarbeitet Videos.

Das Programm verarbeitet Frames. Erfüllt ein Frame bestimmte bedingungen, soll es markiert werden. Nun ist es etwas schwer die Parameter einzustellen wenn man die Frames nicht sieht.

Dazu würde ich mir gerne hin und wieder ein paar Frames anzeigen lassen.

Verfasst: 11. April 2005 10:50
von lepsai
Es ist wichtig, dass Qt selbst mit Threadunterstützung kompilliert worden ist. Das solltest du überprüfen.

kleine Anmerkung am Rande:

// Verhindert, dass das Programm zu früh beendet wird
//mache was.........
while (t.running())
{}

das schreibt man so:

t.wait();

Aber wie gesagt in deinem Fall, darfst du keine Threads benutzen, da dein Konsolenprogramm keine Qt-Anwendung sein darf.

Die GUI selbst muss nicht in ein Thread verpackt werden. Sie läuft schon in einem von Qt geregelten Thread namens "main loop". :)

Verfasst: 11. April 2005 10:55
von december_soul
OK dann bastel ich mir nun eine QTAnwendung und versuche die erstmal über Sockets zu steuern.

Dauert sicher etwas aber das sollte machbar sein.
Im Grunde finde ich diesen weg sogar ganz gut.
Mein Programm kann gerne mal 20 min laufen bis so ein Video analysiert ist.
Dann kann ich die GUI sogar hin und wieder mal anschalten und sehen was das Programm so macht :-)

Verfasst: 11. April 2005 11:37
von Mitsu
Habe vor einiger Zeit mal ein ähnliches Problem gehabt.
Das war eine Konsoleanwendung, die TCP/IP-Frames vom Netz
über einen Funkkanal versendet und empfangen hat. Die Anwendung
läuft normalerweise als multithreaded Konsoleanwendung so vor
sich hin, aber zum Debuggen war ein GUI, mit dem man sich
die internen Zustände anzeigen lassen konnte, eine nützliche Sache.

Realisiert habe ich das GUI damals aber nicht als zusätzlichen Thread,
sondern als eigenständigen Prozess, der mit der Konsoleanwendung
über Shared Memory verbunden ist. Die Konsoleanwendung erzeugt
dabei das Shared Memory Segment und das GUI kann sich an das
Segment jederzeit attachen oder auch nicht. Der Vorteil ist, das die
Konsoleapplikation gar nicht mitbekommt, ob das GUI läuft oder nicht und
sich um nichts zu kümmern braucht.

Verfasst: 13. April 2005 15:05
von december_soul
So ich bin nun dabei das ganze mit sharedMemory zu schreiben.
Erste Versuche gehen auch ganz gut.

Ich glaube ich habe ein kleines Semaphoren problem.

Ich habe zwei Programme die über SharedMemory kommunizieren sollen.

Funzt auch super.
Nur leider glaube ich das etwas mit den Semaphoren nicht stimmt.

Ich habe als Semaphore die erste Stelle von Speicher genommen.

myPtr ist ein Pointer auf meinen Speicherbereich.
Da ich zZ jedoch nur (Text)Nachrichten verschicke, ist es ein char*

Ich kann also mit
sprintf (myPtr+1, "hello world %d",count);

was reinschreiben.
In dem anderen Programm kommt es auch raus.

Nun ist es ja ein Kritischer abschnitt.
Aus diesem Grund wollte ich
myPtr[0]
als Semaphore nutzen.

// KritischerAbschnitt belegen
myPtr[0] = 1;

// KritischerAbschnitt freigeben
myPtr[0] = 0;

// warten bis KritischerAbschnitt wieder frei ist.
while(myPtr[0])
sleep(1);

Nur haut das mit der Semaphore nicht hin.
Weißt einer warum?

Nebenbei will ich eigentlich auch das der Schreibende Prozess nicht warten muß.
Er soll also den Kritischen abschnitt immer betreten dürfen.(wenn er frei ist)
Der Empfänger dagegen soll nur eine Nachricht entnehmen wenn der Kritische Abschnitt frei ist und eine neue Nachricht enthalten ist.
Es ist egal wenn der Empfänger mal eine Nachricht nicht ließt. Ist halt pech.
Es könnte ja sein das der lesende Prozess nicht läuft.

Hier nochmal ein kleiner Ausschnitt aus den Programmen:

Sender:

Code: Alles auswählen

//Konstruktor

    /* Shared Memory erzeugen */
    shID = shmget(2404, MAXMYMEM, IPC_CREAT | 0666);
    if (shID >= 0) {
        // nun holen wir den Speicher
        myPtr = (char*)shmat(shID, 0, 0);
        if (myPtr==(char *)-1) {
            log->logerror("ShardMemory Error: shmat");
        } else {
            initdone = 1;
            myPtr[0] = 0;
        }
    } else { /* shmget lief schief */
        log->logerror("shmget");
    }   

//--Methode zum schreiben der Nachricht------------------------------------------------------
    //wait until semaphor is free
    while(myPtr[0])
        sleep(1);
   
    //set Semaphor
    myPtr[0] = 1;
   
    //write to sharedmemory
    sprintf (myPtr+1, "hello world %d",count); 
   
    //unset Semaphor
    myPtr[0] =0;//write done
   
    //after 199 messages sign the end of the transfer.
    if (cont ==199)
        myPtr[0] =2;
Empfänger:

Code: Alles auswählen

int main(int argc, char **argv)
{
    int shID;
    char *myPtr;
    int i;
    int count = 0;

    /* Existierenden Shared Memory zugreifen */
    shID = shmget(2404, MAXMYMEM, 0666);
    if (shID >= 0)
    {
        myPtr = (char*)shmat(shID, 0, 0);
        if (myPtr==(char *)-1)
        {
            std::cout <<"shmat"<<std::endl;
        }
        else
        {
            while(myPtr[0] !=2)
            {
                //myPtr[0] = 0 der kritische Abschnitt ist frei
                //myPtr[0] = 1 binaar ist im Kritischen Abschnitt
                //myPtr[0] = 2 Ende der Nachrichten
                
                 //wait until KA is free
                while(myPtr[0])
                   sleep(1);
                             
                   myPtr[0] = 1;
                   printf("%s",myPtr);  
                   myPtr[0] = 0;
            }
            shmdt(myPtr);
        }
    }
    else
    { /* shmget lief schief */
        std::cout <<"shmget" << std::endl;
    }
}
Ich hoffe ich habe keine grossen Schnitzer drinne.

Verfasst: 13. April 2005 17:01
von Mitsu
Hmm, prinzipiell kann man natürlich einfach ein Byte aus dem
Shared Memory als Semaphore verwenden, aber der Zugriff
auf diese Speicheradresse ist nicht notwendigerweise atomar.

Günstiger ist die Verwendung einer echten, vom Betriebssystem
bereitgestellten Semaphore. Die System Calls um sich eine
Semaphore zu besorgen ähneln den Calls für Shared Memory.

Eine gute Einführung mit Beispiel läßt sich unter:

Systemprogrammierung - Teil 9
Die Ampel regelt alles
von Wolfgang Hetzler

finden. Link -> http://www.64-bit.de/dokumentationen/progr-software/
a/004/system9.html

Verfasst: 5. Juli 2006 09:21
von freeskydiver
lepsai hat geschrieben: Wenn du Threads benutzt muss Qt zu deinem gesamten Programm gelinkt werden und das geht ja bei dir nicht. Wenn auf dem Zielrechner gar keine Qt installiert ist, ist es nicht gerade vorteilhaft.
kleine Zwischenfrage... passt nicht ganz zum Thema ist aber wichtig.
Wenn ich auf der Zielplattform KEIN Qt Installiert habe ...kann ich doch trotzdem meine Application statisch linken und dann sollte die doch laufen ????? oder hab ich da jetzt was verpasst????
Genau das Problem werde ich in einigen Wochen haben. Ich hab mich für Qt entschieden.

Verfasst: 5. Juli 2006 09:31
von macman
freeskydiver hat geschrieben:Wenn ich auf der Zielplattform KEIN Qt Installiert habe ...kann ich doch trotzdem meine Application statisch linken und dann sollte die doch laufen ????? oder hab ich da jetzt was verpasst????
Ja, das geht.
Nein, Du hast nichts verpasst.