[Qt4] Connectek es threadek egy dll-ben (+ Qt centre forum)

 ( greenvirag | 2008. szeptember 20., szombat - 17:18 )

Kedves hupperek.

Több kérdésem is lenne.
1: Tudja-e valaki mért elérhetetlen mostanában gyakran a qtcentre.org?
2: A problémám maga pedig: (amit amúgy az előbb említett qtcentre.org fórumján ki is fejtettem)

Van egy dll fájlom, amit arra szeretnék használni, hogy bizonyos számításokat elvégezzen. Egy-egy számítás egy-egy threadben fut. Ezt a dll egy kívülről hívható függvénye intézi el úgy, hogy amint befut egy új számításigény, az adatokat szépen beleteszi egy szálba, majd a meghívó számára visszaad egy azonosítót. Később ezzel az azonosítóra hivatkozva lehet például lekérni a megoldásokat.

Egy thread amint megoldást talál, emit-tel egy signalt, amit a solution osztály fogad. Tehát a thread megfelelő része a signal/slot mechanizmust használva kommunikál "standalone objektumokkal" a dll-en belül.

A kérdés pedig ott merül fel, hogy miképp történjen az event handling. Elsőre a kötelező megoldás: QApplication (QApplication::exec(): "It is necessary to call this function to start event handling.").
Csakhogy ez egy olyan ciklusba kezdene, hogy annak végezetéig nem térhetnék vissza a meghívó programhoz
("Enters the main event loop and waits until exit() is called.")

Így kérdeznék minden qt-ben jártas lelkes fórumozót, milyen megoldást javasolnak a problémára.
Még egyszer a kívánt funkcionalitás:

[caller program] start problem in the dll
[dll] receive the call. start a new thread with the problem
[dll] start event handling
[dll] give to the caller program the ID (return ID)
[caller program] receive the ID
[caller program] do something && [dll] working
...
[caller program] get the solution
[dll] give the solution (if finished)

Fontos lenne mielőbb kisütni valamit, szóval előre is köszönöm a segítséget.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Először is nézz körül itt:
http://doc.trolltech.com/4.4/threads.html#qtconcurrent-intro
meg itt:
http://doc.trolltech.com/4.4/qfuture.html

Ez nem az mint amit most kérdeztél, de szerintem lényegesen egyszerűbb megoldása a problémának.

Event handling:
Több event loop is kell, minden thread-ben egy, és a főprogramban is.
Gondolom ez utóbbi van. Legalábbis ha GUI-s a program akkor biztos.
(Ha nincs, akkor QFuture)

Van ugye egy osztályod ami a számításokat végzi. Ennek slot-ban legyen a számításokat végző fv-e, és legyen egy signal-ja ami visszaadja az eredményt.

Hozz létre egy QThread osztályt. Ha nem származtatsz belőle, akkor alapértelmezés szerint a run()-ja csak elindít egy event loop-ot.
A számoló osztály leszármazottját (worker) "rakd át a threadbe" (QObject::moveToThread).
Innentől minden signal-slot connection asynchron lesz.

Csodás, kösd össze a worker signal-ját egy slottal, indítsd el a thread-et, majd hívd meg (signal-slot mechanizmuson keresztül) a worker slotját. Legegyszerűbb a QTimer::singleShot-tal.

Valami ilyesmi:

Worker worker;

connect(&worker, SIGNAL(done(QByteArray)), SLOT(collect(ByteArray)));

QThread workerThread;
worker.moveToThread(&workerThread);

workerThread.start();

QTimer::singleShot(0,&worker,SLOT(work()));

Persze nálad nyilván new-kkal lesznek létrehozba az objektumok, csak nem akartam annyit írni... :)

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Nem irtam le fentebb reszletesen, de:
1. a thread - worker resz egyszeruen ugy lett megoldva, hogy a worker class szarmaztatva van a qthread-bol, igy ilyen teren nincs problema.
2. non-GUI application

Szoval voltakepp csak az a franya main loop ami bezavar, ami ugye az event handling miatt mindenkeppen kell (legalabbis ugy tunik).

Mindenesetre koszonom a valaszt, utananezek a linkelt anyagoknak.

Illetve meg valami:
"Innentől minden signal-slot connection asynchron lesz."
Ez mit jelent pontosan?

1. Az baj... Leginkább azért, mert akkor a thread-ben sincs event loop.

2. Szerintem akkor mindenképp a QtConcurrent/QFuture kell neked, főleg mivel egyáltalán nincs event loop-od, tehát a signal-slot nem is működik szerintem.
http://labs.trolltech.com/blogs/2007/03/08/making-asynchronous-function-calls-with-qfuture/

Tehát a signal-slot alapvetően kétféleképp működhet.
a) szinkron módon:
Ha összekötsz két objektumot azonos thread-ben, akkor ez az alapértelmezett. Ilyenkor az "emit mySignal();" hatására azonnal meghívódnak a csatlakoztatott slot-ok. Valójában egy sima fv hívás történik.
b) aszinkron módon:
Ha összekötsz két objektumot különböző thread-ekből, akkor ez az alapértelmezett. Ilyenkor az "emit mySignal();" hatására a signal csak bekerül egy várakozási sorba, a hívó futása folytatódik, és a slot akkor hívódik meg, mikor a fogadó thread-ben az event loop-hoz kerül a vezérlés.
Lásd itt: http://doc.trolltech.com/4.4/threads.html#signals-and-slots-across-threads

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Nezem, nezem a nagy qt api leirasokat trolltechen, de meg mindig nem vilagos, hogy main loop nelkul hogy mukodhet barmi is.

A threaddel kapcsolatos local event loop letezik QThreadbol valo szarmaztataskor is, csak egyszeruen a run()-ba meg bele kell tenni egy exec()-et. Igy nem ertem, mert jobb a moveToThread, mint rogton a class MyClass: public QThread.

Ha ezen tullepunk, csak felvetodik ujra a kerdes a main loop korul. Az mindenkeppen kell, ha van GUI, ha nincs. A main loopot pedig a QApplication exec() fuggvenyenek meghivasaval erem el.
Tevedek? Mert ha nem, akkor ujra itt a kerdes, hogy ha egyszer belekezd ebbe a main loopba, hogy terhet vissza kozben a caller programhoz, mikozben o maga a hatterben kene hogy fusson.

Ilyeten modon hogy QThread - moveToThread, illetve QFuture csak reszletkerdes lenne.

A moveToThread és a QFuture-nak semmi köze nincs egymáshoz.

Az a lényeg, hogy minden QObject leszármazott egy thread-hez tartozik. Ez le is kérdezhető a QObject::thread()-del.
Ha connect-tel összekötsz két objektumot, akkor az alapértelmezett mód az "auto connection", ami azt jelenti, hogy "direct connection", ha azonos thread-ben vannak, és "queued connection" ha nem.

A moveToThread ahhoz kell, hogy az objektumodat átrakd a másik szálba, azaz a QObject::thread() ne a fő szálat adja vissza. Alapértelmezés szerint minden objektum ahhoz a szálhoz tartozik, aminek a futása alatt létrejött.
Tehát ha te létrehozol egy QThread objektumot, illetve annak konstruktorában további objektumokat, akkor az mind a főszálhoz fog tartozni, és nem a létrehozott QThread-hez.

Azaz a moveToThread-re mindenképp szükséged van, akkor is ha saját QThread osztályt származtatsz. Legalábbis ahhoz mindenképp, hogy automatikusan működjön az aszinkron signal-slot. Talán moveToThread nélkül is működik, ha kézzel megadod neki, hogy "queued connection", de én nem tudom, a Qt még hány helyen használja fel a QObject::thread()-ből származó infót. Gyanítom, hogy assert-ekhez elég gyakran, ami azért nem hátrány...

"A main loopot pedig a QApplication exec() fuggvenyenek meghivasaval erem el."

Egész pontosan a QCoreApplication::exec(). A QApplication már QUI-s.
Nem kötelező az event loop használata, csak akkor kell, ha kezelni akarsz event-eket, illetve signal-slot-ot.
Az event loop, mint a neve is mutatja egy folyamatosn pörgő ciklus, ami begyüjti a beérkező eventeket (pl X-től ablakesemények, stb), majd sorban lekezeli őket.
Illetve kezeli a quened slot hívásokat.

Ehhez viszont az kell, hogy rendszeresen visszakapja a vezérlést.
Ezt pl úgy tudod megtenni, hogy a hosszú feladatot felbontod több kisebb fv-re (ezek slot-ok), majd meghívod az elsőt (QTimer::singleshot 0 idővel), és mindegyik végén meghívod ugyanígy a következőt. Így minden 2 darab között szóhoz jut az event loop.
Másik variáció, hogy rendszeresen meghívod a QCoreApplicaton::preocessEvents-et, ami lényegében ugyanezt csinálja. Persze ehhez is kell, hogy fusson egy exec.
Kb így:

// slot:
void Worker::longRun()
{
   //work
   qApp->ProcessEvents();
   //work
   WorkerThread *wt=WorkerThread;
   wt->start();
   //work
   while (wtIsCompleted)
       qApp->ProcessEvents();

   //work with wt's results
}

int main(...)
{
   QCoreApplication app(argc,argv);
...
   Worker wrk;
   QTimer::singleshot(0,&wrk,SLOT(longRun()));
   returtn app.exec();
}

Ehhez képest QFuture:

Data worker();

int main(...)
{
   QCoreApplication app(argc,argv);

   //work
   QFuture wt = QtConcurrent::run(worker);
   //work
   Data d=f.result();
   //work with wt's results

Szerintem eléggé egyértelmű melyik a kényelmesebb ha csak a párhuzamosság számít, és nincs folyamatos kommunikáció a szálak között...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

A qApp->processEvents()-t felejtsd el.

A Krusaderből is kiszedném az összeset, ha lenne rá elég időm.

Szemét egy függvény, lehet, hogy mire visszatér már maga az objektum sem létezik. A Krusader-ben 10 fagyásból 9-et ezek a függvények okoztak, úgy hogy a felhasználó bezárta az ablakot és a függvényből kilépéskor már a hívó objektum sem létezett.

Érdekes probléma... Én inkább azt mondanám, hogy ésszel kell használni.

Pl ha a Krusaderben mindenhol az objektumokat deleteLater()-rel törölnék, akkor a probléma elvileg megszűnne, mivel a processEvents() a DeferredDelete eventet kihagyja.

Úgyhogy inkább a delete akarmi; sorokat kéne kitörölgetni...

(Mondjuk egy Krusader szintű progiban ahol állandóan olyan műveleteket kell végezni, ami blokkolhatja a GUI-t nem is kezdenék processEvents() használatba...)

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Sajnos az a helyzet, hogy amikor a Krusader fejlesztése elkeződött, még nem értettünk a QT-hez.

Az eseményvezérelt programozás nehézkes volt, így a qApp->processEvents()-szel könnyedén és gyorsan lehetett eljárásvezérelt kódot írni. Ennek az árát persze később fizettük meg, mert a karbantartás nehézkessé vált, az eljárásvezérelt magot eseményvezéreltté átírni meg senkinek sincs kedve.

Minden művelethez (pl. fájlkereséshez) context-eket kellene létrehozni (ami megmondja, hogy hol tartunk éppen), időnként kilépni és QTimer::singleShot(0)-kkal visszahívni önmagunkat. Így visszaadnánk a vezérlést egy időre a GUI-nak, hogy képes legyen feldolgozni az eseményeket. Kezdetben nem így csináltuk a kódot, mert kezdő Qt programozó nem fejjel lefelé nézi a világot.

(már azért elég sok helyen így működik a Krusader)

Ha pedig a fájlkereső ablakot modálissá tennénk (megoldás lenne, mert nem kellenének a context-ek), rögtön 1000 user kiabálna, hogy keresés közben mással is akarnak foglalkozni, nem csak azt lesni, hogy mikor lesz már vége.

A deleteLater() sem biztos, hogy segít, mert az ablak még kint van a képernyőn. Lenyomod a [x]-t, de az ablak csak akkor tűnik el, mikor kilép a rendszer a qApp-processEvents-ből és visszaadja a vezérlést a main loop-nak. Lehet, hogy hide()-ot kellene az ablaknak nyomni, utána deleteLater()-t hívni. Szóval az egész annyira bonyolult, hogy a context kezelés értelmesebb (és jobb) alternatívának tűnik.

Még egy vicc:
- mivel csomó ablak a qApp->processEvents()-eken vár, nem lehet a Krusader-t csak úgy simán bezárni. Kilépéskor egyesével végigmegy a program az összes ablakon, bezárogatja őket. Ha nincs nyitva ablak, akkor biztos, hogy senki sem vár a qApp->processEvents()-ben, így biztonságosan ki lehet lépni.
- ez a gányolás magasfoka :-)

A QTimer::singleShot(0) sem oldja meg a megszünő objektum kérdést.
Ugyanis ha így berakja magát egy fv az event sorba, majd közben szó nélkül elhal (delete), akkor a program ugyanúgy elszáll, mikor az eventloop elér idáig a sorban... Tehát a deleteLater ugyanúgy kell...
Az ablakból kilépés problémáját mondjuk megoldja az tény...

Ahogy ezt így leírtad, csodás gányolás...

Nade mi a baj a thread-ekkel?

Legyen a fájlkeresés maga külön thread, ami signal-slot-tal van hozzákapcsolva a fájlkeresés ablakához (ez thread safe queued connection esetén). Mehet a progressbar, küldheti a fájlneveket, akármit.
A thread indítása után a vezérlés visszajut a fő eventloop-hoz. Mindenki boldog, keresés megy UI gyors.

Az ablakból kilépéskor (closeEvent, vagy destruktor) meg küld egy üzenetet a fájlkereső threadnek, hogy nyírja ki magát, és kész.

A QThread::terminate() erre mondjuk nem jó, mert nem takarít maga után, rögtön kilövi a thread-et, de pl a wxWidgetsben van egy egyszerű megoldás (Delete()/TestDestroy()).
A threadben bizonyos időközönként meghívod a TestDestroy()-t, ami, ha igaz értéket ad, akkor takarítás után gyorsan kilépsz. A TestDestroy() meg akkor ad vissza igazat, ha valaki meghívta a thread-re a Delete()-et.

Szerintem ez tiszta, egyszerű, és könnyen karbantarthatónak tűnik, mindössze az kell, hogy a thread-ek elég gyakran megnézzék nem kell-e kilépniük.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

> Nade mi a baj a thread-ekkel?

A Krusader nem csak helyi fájlokat kezel, hanem ftp-t és smb-t is.

Innentől kezdve meg a thread-ek használhatatlanok, mert a KDE protokoljait nem hiszem, hogy más threadből hívni lehetne, amikor még a GUI threadjéből sem megy a KDE rendesen.

Ha ftp kapcsolatot kezdesz, akkor létrehozol egy objektumot, a KDE meg signal/slot-os rendszerben értesít amikor eredmény jön.

Persze lehet, hogy Qt4-KDE4-nél már több threadből is megoldható lenne ez, egyenlőre nincs tapasztalatom róla.

Szerintem a kio abba a szalba kuldi a signal-t amibe epp vagy.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

A signal-slot threadsafe tud lenni. Ehhez az kell, hogy QueuedConnection legyen. Ilyenkor a signal a fogadóhoz tartozó event sorba kerül, nem pedig közvetlen hívás történik.

Ehhez csak az kell, hogy a connect megkapja az utolsó paramérben, hogy QueuedConnection, vagy a két objektum különböző szálhoz tartozzon (QObject::moveToThread()), ilyenkor autómatikusan QueuedConnection lesz.
Nomeg nyilván a fogadó threadnek kell egy event loop.

Tehát a kio-nak teljesen mindegy, hogy a signaljait milyen thread slotjaihoz kötik.

A fájlkeresésnél maradva, ha a fájlkereső objektum az új threadhez tartozik, signaljait hozzákötve a GUI slojaihoz automatikusan queued connection-t kapunk. Kész.

Ftp esetén is működikhet, ilyenkor maga a thread is eventloop-ot futtat, és slotjai is vannak, amik hozzá vannak kapcsolva a kio-hoz.
Mondjuk ha a kio eleve aszinkron, akkor esetleg nem kell a thread-es bohóckodás.

Úgy tudom ezt elképzelni, hogy a job maga mindig külön van a gui-tól, és a job aszinkron. ftp esetén tehát közvetlenül a kio van bekötve, vagy egy egyszerű wrapper, míg fájlkeresésnél meg kell írni aszinkronra, aminek a legegyszerűbb módja a thread.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Meg mindig nem vilagos hogy most mi, hogyan tortenik.

A kerdes roviden: dll-en belul hogyan hozzunk letre threadeket?

Rengeteg mód van erre, attól függ mit akarsz.

Első kérdés: A főprogram (ami a dll-t használja) Qt-s?

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Tobb projektnel is szuksegem lenne erre.
Az egyik Qt-s, a masik siman c++-os, a harmadik java-jni-n keresztul.
Lehet valogatni. :)

Tehát akkor olyan megoldás kéne, ami egy sima C++-os dll-t eredményez.
Sőt, talán inkább C-set, a JNI miatt.

Ki kéne találni milyen felületet szeretnél, azaz mit tudjon a dll.
Korábban írtál pl signal-os helyzetjelentést, az ugye nyilván nem megy nem Qt-s körülmények között.

Egyébként tuti, hogy az az egyszerűbb megoldás, hogy a dll csinálja a szálkezelést?

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

A dll felulete most nem lenyeges.
Az architektura, amit meg kell valositani:

[program] ---dllHivas---> [megoldokat (es meg par egyebet) kezelo modul] ---dllHivas---> [megoldo1/megoldo2/.../megoldoN]

A megoldokat kezelo dllben szalkezeles kell, mivel a megoldoN futasa idoigenyes.

Azért nem teljesen lényegtelen...
Én valami ilyesmit képzelek:
Job indító fv(ek), isFinished/isRunning fv, terminate, eredmény lekérése.

Ha a szálak teljesen függetlenek egymástól, és nincs szükség threadpool-ra, akkor a job indító fv visszaadhatna egy egyedi id-t, a hozzá tartozó thread-re mutató mutatót pedig letárolnám egy map-be, vagy közvetlenül a mutatót adnám vissza.
Így egyedül az eredmény lekérése lehet trükkös.
Ehhez még Qt se kell, elég egy pthread.

Ha threadpool kell (azaz maximálni akarod a párhuzamosan futó szálak számát), akkor QtConcurrent::run-nal indítanám a job-okat, a visszakapott QFuture-t meg letárolnám. Igaz, így a terminate nem megoldható ha jól látom.

Én nem kezdenék felesleges signal-slot-ozásba, mert ahhoz kell event loop, ami jelen esetben felesleges bonyolítása a problémának. (De egyébként megoldható, csináltam már...)

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Oke. A szalak fuggetlenek egymastol, illetve egy adatbazist hasznalnanak, de arra meg ott a tranzakcio kezeles.

A job id mindenkepp jo otlet, en is igy gondoltam.

Mapben hogy tarolnal dolgokat? Ahhoz kene valami allando valtozo a dll-ben, olyat meg azert nehez csinalni..

Qt azert jobb egy pthread-nel, mert akkor konnyebb windows-re portolni.

A signal-slot jol jon, de nem letkerdes. A letkerdes a threadkezeles.

"Mapben hogy tarolnal dolgokat? Ahhoz kene valami allando valtozo a dll-ben, olyat meg azert nehez csinalni.."

Már miért lenne probléma? Static változód szerintem lehet, vagy static QMap<>, vagy Singleton pattern.
Ha ez vmiért nem működik, még mindig lehet a dll-nek egy init fv-e amit használat előtt kötelező meghívni. (Egyébként asszem van is valami fv a dll-ekben ami meghívódik betöltéskor.)

"A signal-slot jol jon, de nem letkerdes. A letkerdes a threadkezeles."
Akkor minden sokkal bonyorultabb.
Létre kell hozni 1 fő threadben QApplication-t, indítani egy eventloop-ot, és utána már a thread-eknek lehet saját eventloop-ja. Legalábbis elvileg, ilyet még nem csináltam.
De dll-ben hoztam már létre QApplication-t, és működött a direkt signal-slot, eventloop nélkül.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Akkor a signal/slot dolgot mellozve szerinted pontosan miket kene hasznalnom a dllben threadkezeleskent?

Ha nem kell threadpool, akkor én írnék egy saját QThread leszármazottat, ami konstruktorában megkapja a futtatni kívánt fv-t, majd job indításakor létrehoznék egy ilyen thread objektumot, a mutatót letárolnám, és elindítanám.
Persze ha a job eredményt ad vissza, akkor ennek megszerzésére is kellenek megfelelő fv-ek.

Persze lennének egyszerű kisegítőfv-ek is a dll-ben, amik a Thread osztály megfelelő metódusait hívják, miután az id alapján megszerezték a mutatót.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Tehat nem kell main loop a threadezeshez?
Mert eddig ez alapjan azt hittem, hogy kotelezo:

"Note that QCoreApplication::exec() must always be called from the main thread (the thread that executes main()), not from a QThread. (...)
In addition, you must create the QApplication (or QCoreApplication) object before you can create a QThread."

Vegulis ugy is lehet ertelmezni, hogy "ha egyaltalan akarsz main loop-ot (QCoreApplication::exec()), akkor azt csak is a main threadbol hivhatod meg, mielott meg a QThread objektumodat letrehoznad. Ha meg nem akarsz main loop-ot, akkor mindegy is az egesz." ..

Szerintem én már használtam QThread-et event loop nélkül...
Próbáld ki, rögtön meglátod. :)

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Igen, kiprobaltam delelott, tenyleg mukodott.
Ha viszont megis kene event loop, de nem a threadek kozti kommunikaciora, hanem threaden belul peldaul, akkor az siman megoldhato, ha elinditom a thread exec()-jet?

Szerintem igen, de ennyire sosem ástam a Qt forrásának a mélyére.

Ha nem, akkor debug módban valószínűleg kapsz majd egy üzenetet...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o


void *QThreadPrivate::start(void *arg)
{
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
pthread_cleanup_push(QThreadPrivate::finish, arg);

QThread *thr = reinterpret_cast(arg);
QThreadData *data = QThreadData::get2(thr);

pthread_once(&current_thread_data_once, create_current_thread_data_key);
pthread_setspecific(current_thread_data_key, data);

data->ref();
data->quitNow = false;

// ### TODO: allow the user to create a custom event dispatcher
createEventDispatcher(data);

emit thr->started();
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_testcancel();
thr->run();

pthread_cleanup_pop(1);
return 0;
}

Simán pthread-et használ.

--
http://www.naszta.hu

A kérdés az, hogy a Thread EventLoop-ja működik-e a QApplication fő EventLoop-ja nélkül. Elvileg működhet, de ennyire nem látok bele a Qt-ba...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Lehet hogy zöldséget beszélek, de ha számításokat akarsz kiosztani, akkor akár szerver kliens megoldást is alkalmazhatnád. Az én olvasatomban:

van valami program -> küld adatot a DLL-nek -> DLL indít szálat a számításnak (ad IDét) -> DLL visszaadja az infót mikor kérik

Na most ugyanez mehetne úgy is hogy a DLL-t behelyettesíted TcpServerrel, még ha ugyanazon a gépen is fut. Nem olyan bonyolult implementálni és lehet hogy tisztább eredményt kapsz. Lásd példának:

http://doc.trolltech.com/4.3/network-threadedfortuneserver.html

De lehet hogy ez sok keverés, vagy tök nem értem a feladatod :) De a jó szándék legalább megvolt bennem :D

Fölösleges szerintem egy újabb absztrakciós szintet bevezetni, plusz még lassabb is lesz. Egyébként valószínűleg pont ez kell neki, csak TcpServer nélkül.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Igy van.

Egyetértek, csak a DLL megoldást nem vágom hogyan fogja megcsinálni úgy hogy Qtben implementálja slotokkal meg signalokkal és sima C++ ban használja. No mindegy, nem vagyok én programozó csak pék :)

Az hogy a dll-en belul mi tortenik, a meghivo program szamara teljesen mindegy. Az interface meg adott esetben egyszeruen nem fog qt-s tipusokat hasznalni.

1) ettol meg kellenek Qt libek a futtatashoz, hacsak nem teljesen pluginszeruen oldod meg
2) pure C (JNI) eseten ket interfesz kell, egy C-s (JNI-s) meg egy C++-os.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

1- Ez igy van, nem is irtam ettol elterot sehol.
2- Lattam en mar osztalyokat atmenni jni-n keresztul, szoval nem teljesen ertelek.

Egyvalamit nem ertek: nem kell GUI app ahhoz, hogy event loop legyen, eleg a QCoreApplication-t hasznalni. Akkor mar eleve van egy event loop, amin keresztul lehet minket ertesiteni ha van valami ujdonsag.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Persze, eleg a QCoreApplication, de annak el kell inditani az exec fuggvenyet ahhoz, hogy elinduljon a main loop. Dll-en belul pedig hol inditanad el? Nyilvan ha valahol tenyleg elinditod, akkor az a fuggveny nem egyhamar fog visszaterni a hivo programhoz, hanem csak ha vegzett, akkor meg mar a threadezgetesnek sincs ertelme.

Ennek igy nincs ertelme. Valaki ugyis fog egy QApplication-t vagy egy QCoreApplication-t inditani hogy hasznalhassa a DLL-edet (Qt-s appoknal a ketto kozul az egyik kotelezo). Innentol pedig annyira mindegy.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

A feltetelezesed rossz. Ki mondta, hogy Qt-s lesz az alapprogram? Pure C++-os progibol hivva a Qt-s dllt ugyan senki nem fog QApplicationt, vagy QCoreApplicationt letrehozni.

Azert, mert a Qt ojjektumai amennyire tudom kicsit speckon vannak exportalva egy class library-ban, igy erdemesebb Qt alapprogramba gondolkodni. Illetve az importalashoz mindenkepp kellenek majd Qt-s headerek is, szoval... :S
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Ertelek, oke, de en kezdetektol fogva egy tisztan C++-os API-n gondolkodtam. Nyilvan maga a problema is csak ilyen esetben letezik egyaltalan.

-- törölve -