[gelöst] QSharedMemory Benachrichtigung über neue Daten

Alles rund um die Programmierung mit Qt
Antworten
Tuxing
Beiträge: 52
Registriert: 28. Oktober 2009 11:13

[gelöst] QSharedMemory Benachrichtigung über neue Daten

Beitrag von Tuxing »

Guten Tag zusammen,

ich habe mir das Beispiel zu QSharedMemory (http://doc.qt.nokia.com/4.7-snapshot/ip ... emory.html) angeschaut und frage mich, wie man die Anzeige eines neuen Bildes automatisieren könnte.

Ich möchte gerne in Programm A ein Bild laden und es in Programm B automatisch anzeigen ohne auf einen Knopf "Jetzt bitte Bild laden" drücken zu müssen.

Gibt es eine elegante Methode dem Programm B mitzuteilen, dass neue Daten zum laden bereit stehen? Signals-und-Slots sind hier ja eher schwierig anzuwenden ;)

Grüße
Zuletzt geändert von Tuxing am 27. Juni 2012 08:59, insgesamt 1-mal geändert.
DBGTMaster
Beiträge: 190
Registriert: 19. August 2010 10:00

Re: QSharedMemory Benachrichtigung über neue Daten

Beitrag von DBGTMaster »

Habe selber QSharedMemory noch nie verwendet, aber ich wurde es mit einer QTimer lösen (alle x Millisekunden noch Änderung überprüfen)

http://doc.qt.nokia.com/4.7-snapshot/qtimer.html
Tuxing
Beiträge: 52
Registriert: 28. Oktober 2009 11:13

Re: QSharedMemory Benachrichtigung über neue Daten

Beitrag von Tuxing »

Da habe ich auch schon dran gedacht. Aber es hätte ja sein können, dass es noch was eleganteres gibt.

Danke schonmal
Tuxing
Beiträge: 52
Registriert: 28. Oktober 2009 11:13

Re: QSharedMemory Benachrichtigung über neue Daten

Beitrag von Tuxing »

Also ich habe gerade mal ein paar Tests gemacht. Dazu habe ich mit OpenCV die Bilder meiner Webcam ausgelesen und wollte diese jetzt alle 40 msec ( ca. 25 fps) in den SharedMemory Bereich schreiben. Zunächste habe ich den SharedMemory Bereich initialisiert, indem ich ein Bild von der Webcam geholt habe und die entsprechende Größe reserviert habe:

Code: Alles auswählen

int Webcam::initSharedMemory(QString p_key)
{
    this->m_sharedMemory.setKey(p_key);

    IplImage* ipl_image = this->getOpenCvImg();
    QImage image((uchar*) ipl_image->imageData, ipl_image->width, ipl_image->height, QImage::Format_RGB888);

    QBuffer buffer;
    buffer.open(QBuffer::ReadWrite);
    QDataStream out(&buffer);
    out << image;
    int size = buffer.size();

    if( !this->m_sharedMemory.create(size) )
    {
        connect(&this->m_sharedMemoryTimer,SIGNAL(timeout()),this,SLOT(slotWriteToSharedMemory()));
        this->m_sharedMemoryTimer.start(40);
        return 0;
    }

    return -1;
}
Gleichzeitg verbinde ich einen Timer mit einem Slot zum beschreiben des Bereichs. D.h. alle 40msec wird ein Bild in den Bereich geschrieben.

Code: Alles auswählen

void Webcam::slotWriteToSharedMemory()
{
    IplImage* ipl_image = this->getOpenCvImg();
    QImage image((uchar*) ipl_image->imageData, ipl_image->width, ipl_image->height, QImage::Format_RGB888);

    QBuffer buffer;
    buffer.open(QBuffer::ReadWrite);
    QDataStream out(&buffer);
    out << image;
    int size = buffer.size();

    this->m_sharedMemory.lock();
    char *to = (char*) this->m_sharedMemory.data();
    const char *from = buffer.data().data();
    memcpy(to, from, qMin(this->m_sharedMemory.size(),size));
    this->m_sharedMemory.unlock();
}
Allerdings ist das ganze furchtbar langsam. Parallel dazu lasse ich mir die Bilder der Webcam in einem QLabel anzeigen. Die Anzeige hängt aufgrund des ständigen kopierens in den Speicher total hinterher.

Gibt es vielleicht eine bessere Möglichkeit um Bilder zwischen Programmen auszutauschen ?

Danke schonmal
Herzogswalder
Beiträge: 79
Registriert: 11. Oktober 2009 00:37
Wohnort: Dresden

Re: QSharedMemory Benachrichtigung über neue Daten

Beitrag von Herzogswalder »

Wenn beide Programme von dir geschrieben werden, kannst du die Übergabe auch mit QLocalServer und QLocalSocket machen.
Gruß, Herzogswalder
Qt 4.8, OS X Mountain Lion
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: QSharedMemory Benachrichtigung über neue Daten

Beitrag von RHBaum »

Shared Memory ist die schnellste Art der IPC.
Das wurd ich ned durch Sockets austauschen, wenn keine notwendigkeit dazu besteht. Auch wenn der netzwerkstack aus lokalen verbindungen wahrscheinlich sowieso ne pipe macht.

Bissi Kopf einschalten sollt man dann doch.

Ok, der Server vom SHM schreibt daten, der client bekommts ned mit ! Was tun ?
RIchtig, den client informieren. da der client extprozess ist, gehts sowieso nur ueber IPC.

Welche Möglichkeiten hat man da ?

Klar sockets ... aber da iss das handling dan umstaendlicher als alles andere.
Ausserdem wenn ich SHM mache, will ich meistens ned noch nen socket dazu ^^

Pipes. (besonders msg - pipes) definitiv Ne Möglichkeit. man wird bei groesseren Projecten sowieso nicht nur einen gemeinsam benutzten SPeicherbereich haben, sondern auch anders daten austauschen.
vortiel bei pipes ist, du kannst nen signal kriegen, wenn neue daten ankommen, d.h. du muesstest nicht expliziet pollen.

Semaphoren !

Signale ! der traditionelle und einfachste weg, wenn die Serverandwendung den client kennt. und du braeuchtest nicht pollen !


Hoehere IPC durch BS oder Anwendungsschicht:
Ja auch da geht was. DBUS wenn man mag, iss gerade zu geschaffen fuer sowas ...

Ciao ....
Tuxing
Beiträge: 52
Registriert: 28. Oktober 2009 11:13

Re: QSharedMemory Benachrichtigung über neue Daten

Beitrag von Tuxing »

Ich hatte gedacht, dass Qt dafür vielleicht auch was bereit stellt. Ich hab jetzt komplett auf QSharedMemory verzichtet und verwende jetzt ein Middleware (OpenSplice DDS) zur Kommunikation zwischen den Prozessen. Im Grunde macht die Middleware nichts anderes als einen SharedMemory Bereich anzulegen. Sie nimmt mir aber die komplette Verwaltung bezüglich des benachrichtigen und aufräumen des Speichers ab. Ich muss ja das Rad nicht neu erfinden ;)

RHBaum hat schon recht, dass Sockets zum benachrichten nicht die eleganteste Lösung ist. Mit msg-pipes habe ich mich bisher nicht beschäftigt aber ich werde mir das mal anschauen. Vermutlich macht OpenSplice sowas in der Art auch intern. An solche Semaphor geschichten hatte ich auch schon gedacht, aber ebenfalls keine elegante Lösung.

DBUS kannte ich bisher auch nicht, aber wenn ich mein Problem jetzt nicht schon anders gelöst hätte, wäre das glaube ich meine Wahl gewesen.

Also für alle die mal was in die Richtung IPC machen wollen kann ich nur DBUS oder OpenSplice empfehlen. Es wird einem aufjedenfall viel frickelei erspart ;) OpenSplice wird zudem in Kombination mit IDL (Interface Description Language) verwendet. Man ist somit auch relativ flexibel und kann so ziemlich alle Datentypen irgendwie verschicken.
Antworten