Название: [SOLVED] Подключение dll на Qt к приложению на С Отправлено: Gorthaur от Ноябрь 29, 2005, 17:47 Вопрос вот в чем:
Есть виндозное консольное приложение. И есть dll, написаная на Qt. В длл реализуется наследник QServerSocket, через который консольное приложение производит обмен данными по сетке. Код:
pDllInit() - функция, импортируемая из длл. Её роль - инициализация длл. В даном варианте сильно упрощена: Код:
И все бы хорошо, но проблема в том, что в длл присутствуют сигналы-слоты и для их обработки нужно стартовать event loop... Если переделать функцию инициализации: Код:
то все прекрасно работает, сервер подхватывает сетевые соединения клиентов но естественно до завершения app.exec() управление в main() не возвращается (тоесть фактически никогда не возвращается). А нет ли способа запустить event loop "внутри" dll и вернуться в main для дальнейшей работы? (Напомню что в main() стартануть event loop нет возможности поскольку он не использует qt) Если есть какие-нибудь идеи - поделитесь плз... Заранее thanks. Название: [SOLVED] Подключение dll на Qt к приложению на С Отправлено: Dendy от Ноябрь 29, 2005, 21:43 Есть такой способ! :D
Для работы событийного механизма и всего прочего, что завязано на главном цикле собственно сам главный цикл и не нужен. Итак, в dll полюбому нужно создать класс приложения, который будет жить пока dll висит в памяти: Код: FWDLLServer * DLLServer = 0; Обязательно нужно прибить все данные, что насоздавала либа, поетому не обойдёмся без: Код: extern "C" __declspec(dllexport) void DLLDestroy() А вот события будут передаваться когда ручками буим проталкивать пришедшие события: Код: extern "C" __declspec(dllexport) void DLLProcessEvents() Гатова! Осталось периодически вызывать DLLProcessEvents() из Си-шной проги :wink: Название: [SOLVED] Подключение dll на Qt к приложению на С Отправлено: Gorthaur от Ноябрь 29, 2005, 21:49 Проблема, кажется, нашла свое решение... В Qt Solutions присутствует замечательная фича под названием QMfcApp... В принципе можно обойтись и без нее
Код:
Воспользовавшись идеями из этого полезного решения можно написать свой DllMain в длл... Код:
Сие позволяет иметь Qt event loop в длл отдельно от main event loop приложения (наск я понял...) Единственная проблема - при компиляции выскакивает ошибка Цитировать moc_fwdll.obj : error LNK2005: _DllMain@12 already defined in fwdll.obj Гугл показал что даная ошибка - обычное дело при создании dll со своим DllMain в майкрософтовских IDE и касается не только qt проектов. Причем фиксится она только при помощи шаманского бубна... (У некоторых она возникает только если закрыть Visual Studio а потом снова зайти и сделать полный Rebuild проекта). Если кто сталкивался с подобной багой - помогите пофиксить плз! [/quote] Название: [SOLVED] Подключение dll на Qt к приложению на С Отправлено: Gorthaur от Ноябрь 29, 2005, 21:52 Dendy спасибо за ответ!
К сожалению твой вариант потестить сегодня не успеваю. Завтра обязательно кину результат. regards Название: [SOLVED] Подключение dll на Qt к приложению на С Отправлено: Gorthaur от Ноябрь 30, 2005, 14:25 Цитата: "Dendy" Осталось периодически вызывать DLLProcessEvents() из Си-шной проги :wink: Да решение работает! Но проблема при таком подходе полностью не исчезает :( Если сделать так: Код:
То управление хоть и вернется в мейн но паралельных event loops для main и dll не получится :( Дело в том, что для уведомления сишной части я dll-ке при ее инициализации передаю указатели на callback функции, которые собственно и уведомляют потом сишную часть о новых подключениях, прибытии/отправке данных и т.д. Поэтому сами события внутри dll для сишной части (блин запарил уже этот "термин" :) ) не особо интересны. Тут скорее вопрос стоит так - как бы запустить для dll отдельный поток со своим event loop... Чесно говоря под windows до этого мало приходилось писать... Видимо придется покупать Рихтера... :( Название: [SOLVED] Подключение dll на Qt к приложению на С Отправлено: Dendy от Ноябрь 30, 2005, 15:42 Дик, друже! Не розумію у чому проблема. Мережева частина у Qt зроблена таким чином, що не потребує зайвих асінхроних потоків. Навпаки - ти тільки погіршиш архітектуру та наробиш помилок, якщо заюзаєш зайвий потік.
Тож все просто: робиш у DLL якийсь екземпляр класу, що буде приймати сигнали від сокетів та смикати callback-функції з якимись параметрами. Название: [SOLVED] Подключение dll на Qt к приложению на С Отправлено: Gorthaur от Ноябрь 30, 2005, 16:34 Цитата: "Dendy" Дик, друже! Не розумію у чому проблема. Мережева частина у Qt зроблена таким чином, що не потребує зайвих асінхроних потоків. Навпаки - ти тільки погіршиш архітектуру та наробиш помилок, якщо заюзаєш зайвий потік. Тож все просто: робиш у DLL якийсь екземпляр класу, що буде приймати сигнали від сокетів та смикати callback-функції з якимись параметрами. Я так и делаю. Ты наверное неправильно меня понял насчет потока... Смотри: например мне на сокет приходят новые данные - откуда я знаю что они пришли? Я об этом знаю потому что происходит автоматически emit readyRead(), который я перехватываю например так Код:
А все эти дела с событиями-обработчиками в qt диспетчерит QApplication. Если бы этот код выполнялся в обычном exe, я бы просто добавил return app.exec() в main() и все бы работало на ура. Но мой код должен выполняться в dll, где я не могу создать int main() { ... return app.exec(); }, и выполняться этот код должен независимо (т.е все части приложения работают паралельно, обмениваясь информацией через callback функции, а не ждут завершения друг друга для продолжения работы). Твой пример как раз показывает это - для того, чтобы обрабатывались собития в длл, основной поток приложения (в данном случае main()) должен явно вызывать функцию из длл. Тоесть тот же обычный main qt-шного приложения, вынесеный в сишную прогу а не два паралельно выполняющихся "приложения" как хотелось бы... Мне кажется что если я в DllMain при DLL_PROCESS_ATTACH создам отдельный поток, в который и помещу экземпляр моего сервера - то все должно получиться. Основной поток при загрузке либы вызовет DllMain, и вернется к выполнению своих задач, после чего получится то что мне нужно - 2 независимых потока - в одном С в другом Qt... :) Осталось только разобраться как поредачить Makefile чтобы исчезла ошибка дублирования DllMain и протестировать все на практике :( Никак не пойму в чем именно проблема у линкера... Название: [SOLVED] Подключение dll на Qt к приложению на С Отправлено: Dendy от Ноябрь 30, 2005, 16:54 Якщо ти вважаєш, що ввімкнення циклу подій розв'яже та полегшить твою задачу, то трохи помиляєся. Головна програма зі своїм циклом однаково буде у С-програмі. CALLBACK функції з іншого потока, створенного у DLL викликатися не будуть у головному потоці! Вони будуть викликатися з потоку Qt, що призведе до конфліктів з данними. Бо ті самі дані у той самий час юзаю головний поток С. Фактично ці CALLBACK функції повинні викликатися асінхронно між ітераціями головного циклу С-програми, у потоці С-програми. Щоб цього добитися треба буде обв'язатися мутексами, але це однаково призведе до архітектури сінхронної однопоточної програми. Тож якщо Qt-потік не повинен дані оброблювати, то він нах. не потрібен. Він заважає та робить архітектуру складніше заради... заради нічого :)
Твою С-програму я бачу так: Код: void connectionCallback( int client ); Сінхрона прога має виглядати саме так. Так чи інакше ти прийдеш саме до цього варіанту :wink: Название: [SOLVED] Подключение dll на Qt к приложению на С Отправлено: Gorthaur от Ноябрь 30, 2005, 19:55 Да, ты 100 раз прав что с синхронной прогой намного легче работать и меньше гемороя, но к сожалению реальная ситуация такова, что код сишной проги у меня практически нет возможности модифицировать, кроме того не до конца ясна ее архитектура и выяснить ее тоже нет особой возможности (разве что дезасемблированием сопутствующих длл)... Известен только публичный интерфейс и набор каллбеков которые можно использовать. Фактически сетевая часть лепится сбоку и потому вынуждена на себя брать кучу несвойственных функций. К примеру приложение часто выполняет длительные операции (например дефрагментацию FS) и может быть остановлена по команде "Стоп"... Я могу только предполагать как она эту команду в процессе выполнения дефрага получит - возможно она разбита на итерации в конце которых идет проверка нажат ли стоп (дёрнулся ли каллбек отвечающий за останов). И если принять теперь вариант с синхронной работой длл, то эти предполагаемые итерации в принципе можно было бы дополнить вызовом qtDllProcessEvents() чтобы дать возможность каллбекам сработать (причем опытным путем выяснилось, что processEvents() нужно вызвать несколько раз подряд иначе вся цепочка взаимозависимых событий\слотов не успевает сработать и длл не дергает за каллбек), но сделать это не представляется возможным в виду вышеизложеного... Да и с точки зрения красивой архитектуры неизвестно что лучше в этом случае (да и вообще тут уже о красотах и речи нет... Достаточно бы было кривой, но работоспособности) :) В общем с потоками скорее всего мучиться придется все равно... Или забить на qt в этом проэкте. :(
Название: [SOLVED] Подключение dll на Qt к приложению на С Отправлено: Zmey от Декабрь 01, 2005, 09:54 Имейте совесть, пишите на русском языке. Я же не пишу на белорусском, а кто-то на казахском, кто-то на татарском?
Название: [SOLVED] Подключение dll на Qt к приложению на С Отправлено: Gorthaur от Декабрь 01, 2005, 17:44 В общем после того как я разобрался с ошибкой изза DllMain (проблема была в том, что я совместил объявление и реализацию этой функции в хидере а не разнес их в разные файлы - это не понравилось кьютешному moc ), и создал отдельной поток, в котором создается мой DLLServer и запускается событийный цикл qt ( qApp->exec(); )- все получилось как я хотел. Обмен инфой происходит через глобальные указатели на каллбек функции, которые мне присылает екзешник при инициализации длл. По видимому мне очень повезло и все вопросы с правильными блокировками внутренних вызовов в exe решает сам exe... Кьютешной же либе остается только вовремя дергать за нужный каллбек.
Название: [SOLVED] Подключение dll на Qt к приложению на С Отправлено: Dendy от Декабрь 01, 2005, 19:19 Ухх... Дивись щоб програма не завалилася на рівному місці! :D Ти хочаб організував безпечний доступ к даним з різних потоків?
|