Russian Qt Forum

Qt => Работа с сетью => Тема начата: dim.lian_net от Июля 20, 2013, 11:21



Название: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: dim.lian_net от Июля 20, 2013, 11:21
Добрый день.
Помогите, пожалуйста, понять в чем может быть проблема.
Имеется приложение написанное на Delphi и библиотека для связи с удаленным серваком по TCP написанная на  Qt с использованием QTcpSocket. Для того, чтобы в библиотеке работал Qt-eventloop в DllMain библиотеки завожу поток и запускаю в его контексте QCoreApplication::exec().
После этого при вызове библиотечной функции происходит инициализация работы библиотеки, а именно - запускается поток, в контексте которого заводится QTcpSocket. Связываются сигналы со слотами и т.д. Данные приходят и обрабатываются. Реализовано завершение работы библиотеки с удалением сокета и остановкой потока...
Все работает! Но есть одна проблема - основная прога виснет при попытке выгрузить библиотеку. а именно на вызове FreeLibrary. Выяснилось, что если в библиотеке не вызывать connectToHost() то она выгружается благополучно.
Отзовитесь, кто сталкивался с подобным?


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: merke от Июля 20, 2013, 13:04
Происходит ли при выгрузке либы вызов внутри нее функции дисконекта от хоста, остановка потоков и так далее?


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: dim.lian_net от Июля 20, 2013, 15:04
Дисконнект, остановка потока, удаление сокета и потока происходит еще до выгрузки библиотеки, посредством вызова ее функции. И только после этого пытаюсь выгрузить библиотеку.


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: Old от Июля 20, 2013, 15:13
Что значит "запускаю в его контексте QCoreApplication::exec()"?
Завершается цикл нормально?
Почему не использовать QEventLoop?


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: dim.lian_net от Июля 20, 2013, 15:35
Что значит "запускаю в его контексте QCoreApplication::exec()"?
Завершается цикл нормально?
Почему не использовать QEventLoop?


Создаю поток, связываю сигнал started() c Qt::DirectConnection со слотом, в котором запускается QCoreApplication::exec(). Т.е. QCoreApplication запускаестя из потока, для того, чтобы не блокировалась загрузка библиотеки в DllMain. При этом Qt выводит сообщение, о том, что QCoreApplication запущен не в основном потоке, но связка сигналов все равно работает.

С завершением потока, в котором запущен QCoreApplication::exec() проблем нет т.к. либа не выгружается, только если делали connectToHost(). В любом случае связка от таймеров отрабатывается, и все вертится как надо.
К тому же в последствии я выделил запуск потока с QCoreApplication  в отдельную библиотеку, которую вообще не выгружаю.

А разве можно использовать QEventLoop без QCoreApplication??? Я пробовал, но Qt ругается и коннекты не обрабатывает.


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: Old от Июля 20, 2013, 15:42
При этом Qt выводит сообщение, о том, что QCoreApplication запущен не в основном потоке, но связка сигналов все равно работает.
Вот это меня и смущает.

Экземпляр QCoreApplication создавать придется все равно, а после этого можно использовать QEventLoop в нужных местах.


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: dim.lian_net от Июля 20, 2013, 16:18
При этом Qt выводит сообщение, о том, что QCoreApplication запущен не в основном потоке, но связка сигналов все равно работает.
Вот это меня и смущает.

Экземпляр QCoreApplication создавать придется все равно, а после этого можно использовать QEventLoop в нужных местах.

Дык я и создаю, но создаю его не в основном потоке. Он и крутится в этом потоке, при этом пробрасывает мне сигналы. Но дело то не в этом, а в том, что либа не выгружается, только если я сделаю connectToHost(). Такое впечатление, что ранне сконнекченый сокет удаляется не так, как сокет, который не коннектился (несмотря на disconnectFromHost(), close(), abort() и т.д.). Причем под отладчиком если встать на выгрузке либы и пробежаться по деструкторам, оно иногда выгружается. Как будто требуется время, чтобы освободить какие-то ресурсы.


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: Old от Июля 20, 2013, 16:29
что либа не выгружается, только если я сделаю connectToHost().
Метод connectToHost выполняется асинхронно, т.е. eventloop для него жизненно важен. Вы создаете экземпляр QCoreApplication в одном потоке, а цикл запускаете в другом. Qt об этом вас предупреждает.
Я вам предлагаю попробовать использовать локальный объект QEventLoop внутри нитки, который при ее завершении разрушиться.
А QCoreApplication::exec оставить в покое.



Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: dim.lian_net от Августа 17, 2013, 10:56
Дело в том, что QEventLoop не фунциклирует без QApplication. При его запуске, Qt так об этом и говорит. Может я чего-то не так делаю? Есть пример кода?


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: Old от Августа 17, 2013, 12:09
Дело в том, что QEventLoop не фунциклирует без QApplication. При его запуске, Qt так об этом и говорит. Может я чего-то не так делаю? Есть пример кода?
Конечно не функционирует, объект QCoreApplication/QApplication придется создавать все равно. Но в дочерних потоках не нужно использовать его метод exec, лучше создавать свои экземпляры QEventLoop.


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: dim.lian_net от Августа 17, 2013, 12:25
Итак:
1) Приложение не на Qt и QCoreApplication в нем НЕТ!
2) DLL использует QThread , обрабатывает данные от сокета АСИНХРОННО в потоке.
Где должен создаваться QCoreApplication???
И где вызывать его метод exec()?


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: Old от Августа 17, 2013, 13:00
Итак:
1) Приложение не на Qt и QCoreApplication в нем НЕТ!
2) DLL использует QThread , обрабатывает данные от сокета АСИНХРОННО в потоке.
Где должен создаваться QCoreApplication???
И где вызывать его метод exec()?
Например в DllMain.
Его метод exec нигде вызывать не надо.


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: dim.lian_net от Августа 17, 2013, 13:22
А если НИГДЕ НЕ ВЫЗЫВАТЬ exec(), то как будут сообщения то доходить???
Вы так пробовали??? Работает?


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: Old от Августа 17, 2013, 13:28
А если НИГДЕ НЕ ВЫЗЫВАТЬ exec(), то как будут сообщения то доходить???
::)
В рабочих потоках, в методе run, нужно использовать свои объекты QEventLoop и их метод exec или использовать метод exec QThread (что по сути одно и тоже).


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: Bepec от Августа 17, 2013, 13:34
 Тут закавыка интересная. QThread не запуститься без QApplication. Точнее не запуститься его цикл событий.

Я добился работы только при создании отдельного winApi потока.


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: Old от Августа 17, 2013, 13:40
Тут закавыка интересная. QThread не запуститься без QApplication. Точнее не запуститься его цикл событий.
А в чем проблема создавать экземпляр QCoreApplication?


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: dim.lian_net от Августа 17, 2013, 13:40
В Dllmain  при DLL_PROCESS_ATTACH: создаю объект QCoreApplication core(argc,0);
НЕ ВЫЗЫВАЮ exec();
создаю поток QThread() и в методе run(); вызываю exec();
то Qt выдаeт: "QEventLoop: Cannot be used without QApplication" и соответственно сигналы не работают.


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: dim.lian_net от Августа 17, 2013, 13:43
А зачем его создавать, если eventloop не запускать?


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: Bepec от Августа 17, 2013, 13:48
eventLoop не запускается, если он не создан в отдельном WinApi потоке.Во всяком случае мне его заставить работать не удалось без потока. Мб чуть попозже посмотрю свои исходники - кину.


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: dim.lian_net от Августа 17, 2013, 14:09
А без QCoreApplication::exec() он может работать?


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: Old от Августа 17, 2013, 14:11
В Dllmain  при DLL_PROCESS_ATTACH: создаю объект QCoreApplication core(argc,0);
НЕ ВЫЗЫВАЮ exec();
создаю поток QThread() и в методе run(); вызываю exec();
то Qt выдаeт: "QEventLoop: Cannot be used without QApplication" и соответственно сигналы не работают.
Ага. Создаете экземпляр QApplication на стеке и он разрушается при выходе из DllMain.


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: xokc от Октября 03, 2013, 15:47
И всё-таки, кому-нибудь удалось запустить механизм сигнал/слот внутри dll из консольного не Qt Windows приложения?


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: Bepec от Октября 03, 2013, 16:39
Из консольного не пробовал, но из обычного получалось.


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: xokc от Октября 04, 2013, 09:29
Из консольного не пробовал, но из обычного получалось.
Неоднократно тут на форуме встречал твоё обещание выложить кусочек кода на эту тему :).
Если не затруднит, покажи свою реализацию DLLMain.


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: Bepec от Октября 04, 2013, 09:33
Омм... Это да, постоянно забываю найти и выложить.

PS если ещё припомнишь что я там обещал выложить - напиши в ЛС. А то пипец на работе заставляет забывать :) Разгрести надо.


Название: Re: Dll на Qt + QTcpSocket для вызова не в Qt-приложении
Отправлено: xokc от Октября 09, 2013, 15:11
Раз уж публично попрекнул Вереса невыполнением обещаний, публично и поблагодарю.
Тут обещанное выложено http://www.prog.org.ru/topic_25323_0.html
И таки-да, оно работает. Проблема у меня лично была в том, что для того, чтобы заработали циклы обработки сообщений в DLL нужно было все объекты, которые участвуют в процессе сигнал/слот, создавать в той же потоковой функции, где создается QCoreApplcation.