Russian Qt Forum
Май 16, 2024, 09:13 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: ActiveQt - сервер и клиент в dll  (Прочитано 12614 раз)
kirill
Гость
« : Май 05, 2010, 15:16 »

Прошу помощи!
Сделал сервер
Код
C++ (Qt)
// .h
class AxRoll : public QMainWindow, public QAxBindable
// .cpp
#include <QAxFactory>
QAXFACTORY_DEFAULT(AxRoll,
                  "{FD11A5A4-B433-49e1-A0E5-40496D16EC0B}",
                  "{D1A36ABB-16AE-4cd1-BAEE-D7C77F1F80EA}",
                  "{4CD7F9AF-BDAC-4e21-A2C4-291102674DF8}",
                  "{DD5F39F0-AA74-4441-8F4E-A1E26F97A88A}",
                  "{CB2FD6FF-E56A-4e76-ABE4-741066BF70AA}")
 
AxRoll::AxRoll(QWidget * w)
: QMainWindow(w)
{
  setCentralWidget(new QLabel("TEST LABEL", this));
}
 

Поместил его в dll

Код:
CONFIG += dll qaxserver

Соответственно сделал клиента в .exe
Код
C++ (Qt)
{
  QAxWidget * rollWidget = new QAxWidget;
  rollWidget->setControl("{FD11A5A4-B433-49e1-A0E5-40496D16EC0B}");
  rollWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
 
  QVBoxLayout * vl = new QVBoxLayout;
  vl->setSizeConstraint(QLayout::SetMinAndMaxSize);
  vl->addWidget(rollWidget);
  setLayout(vl);
}
 

ВСЕ чудесно работает.
Переношу клиента в dll и делаю exe, использующий эту dll.
Все точно также прекрасно работает. НО! При выходе из приложения процесс exe остается висеть в памяти. Чего не было на связке dll(сервер) — exe(клиент). А на связке dll(сервер) — dll(клиент) — exe похоже не выгружается dll(клиент).

Как такое побороть?
dll(клиент) линкуется к exe статически через .lib файл.
Ппробовал загружать клиентскую dll динамически и делать ей unload() — не помогает...
Записан
Sanya
Гость
« Ответ #1 : Май 06, 2010, 07:01 »

А под чем компилишь?
У меня в Qt Creator как-то "неохотно" это все компилилось, а в MS VS + Qt "на ура".
Записан
kirill
Гость
« Ответ #2 : Май 06, 2010, 07:23 »

А под чем компилишь?
У меня в Qt Creator как-то "неохотно" это все компилилось, а в MS VS + Qt "на ура".

MS VS + Qt
Записан
Sanya
Гость
« Ответ #3 : Май 06, 2010, 08:08 »

А что если подгружать dll клиента явно и при окончании работы делать ей FreeLibrary() или __FUnloadDelayLoadedDLL()
Записан
kirill
Гость
« Ответ #4 : Май 06, 2010, 08:34 »

А что если подгружать dll клиента явно и при окончании работы делать ей FreeLibrary() или __FUnloadDelayLoadedDLL()

Ппробовал загружать клиентскую dll динамически и делать ей unload() — не помогает...
Записан
Sanya
Гость
« Ответ #5 : Май 06, 2010, 11:00 »

Стоп.
А подгружаешь по средствам QLibrary?
Может имеет смысл через виндовые LoadLibrary?
Не знаю поможет ли, но как вариант ...
Записан
kirill
Гость
« Ответ #6 : Май 06, 2010, 14:24 »

Стоп.
А подгружаешь по средствам QLibrary?
Может имеет смысл через виндовые LoadLibrary?
Не знаю поможет ли, но как вариант ...

Блин уже крыша едет.

Сделал так.
В dll - сервер.
Из exe вызываю.
Так вот если вызывать сервер из конструктора вот так
Код
C++ (Qt)
MainWindow::MainWindow(QWidget * parent)
: QMainWindow(parent)
{
  QAxWidget * wid = new QAxWidget;
  wid->setControl("{E437F37D-53BC-4d2c-97BD-31BC413204F9}");
  wid->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  setCentralWidget(wid);
}
 

То все работает и при выходе процесс успешно завершается.
Но вот если я стану создавать ActiveX не в конструкторе, а в каком нибудь слоте, то процесс не завершается.
То есть
Код
C++ (Qt)
MainWindow::MainWindow(QWidget * parent)
: QMainWindow(parent)
{
  setCentralWidget(new QWidget(this));
}
//некий slot
void MainWindow::newFile()
{
  QAxWidget * wid = new QAxWidget;
  wid->setControl("{E437F37D-53BC-4d2c-97BD-31BC413204F9}");
  wid->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  wid->show();
}
 

То тогда при приложение не завершается при закрытии.
a.setQuitOnLastWindowClosed(true); ставил
setAttribute(Qt::WA_DeleteOnClose); тоже ставил

чо за нафиг. ничо не понимаю
Записан
Sanya
Гость
« Ответ #7 : Май 06, 2010, 14:43 »

Эм ... по приведенным примерам плохо понял(у меня тоже голова кипит), но такое чувство, что просто когда ты делаешь в конструкторе setCentralWidget(wid), то QMainWindow запоминает ссылку на wid и при вызове деструктора неявно удаляет объект. А когда ты делаешь в слоте, то QAxWidget * wid = new QAxWidget просто создает объект в памяти и по завершении работы функции/слота переменная wid грохается, а с ней и вся информация по тому где ж теперь новоиспеченный QAxWidget.
Выйти мона следующим образом:
Код:
class MainWindow: public QMainWindow
{
pablic:
  QAxWidget *wid;
}
/*
тили, тили, трали-вали: создали, вызвали
*/
MainWindow::~MainWindow(
  delete wid;
)
Записан
BRE
Гость
« Ответ #8 : Май 06, 2010, 14:44 »

Попробуй задавать parent.
Код
C++ (Qt)
void MainWindow::newFile()
{
  QAxWidget * wid = new QAxWidget( this );
  ...
}
 

или попробуй принудительно удалять объект.
Записан
kirill
Гость
« Ответ #9 : Май 06, 2010, 15:00 »

Попробуй задавать parent.
Код
C++ (Qt)
void MainWindow::newFile()
{
  QAxWidget * wid = new QAxWidget( this );
  ...
}
 

или попробуй принудительно удалять объект.


Задавал парента, удалял руками, увы, процесс остается в памяти.
То есть, я закрываю главное окно (установлено a.setQuitOnLastWindowClosed(true)Подмигивающий и смотрю в деструктор не приходим.
Ладно, ставлю тогда главному окну setAttribute(Qt::WA_DeleteOnClose);
Вылетает алерт
Код:
HEAP[ActiveQtClient_d.exe]: Invalid Address specified to RtlValidateHeap( 00B20000, 0012FE98 )
Windows has triggered a breakpoint in ActiveQtClient_d.exe.

This may be due to a corruption of the heap, and indicates a bug in ActiveQtClient_d.exe or any of the DLLs it has loaded.


То есть пишет что возможно не выгружена dll.
Чем можно посмотреть, что держит процесс и не дает ему закрыться?
Я конечно могу прибивать по exit(0) но это не наш путь, надо понять что происходит
Записан
kirill
Гость
« Ответ #10 : Май 06, 2010, 15:05 »

Эм ... по приведенным примерам плохо понял(у меня тоже голова кипит), но такое чувство, что просто когда ты делаешь в конструкторе setCentralWidget(wid), то QMainWindow запоминает ссылку на wid и при вызове деструктора неявно удаляет объект. А когда ты делаешь в слоте, то QAxWidget * wid = new QAxWidget просто создает объект в памяти и по завершении работы функции/слота переменная wid грохается, а с ней и вся информация по тому где ж теперь новоиспеченный QAxWidget.
Выйти мона следующим образом:
Код:
class MainWindow: public QMainWindow
{
pablic:
  QAxWidget *wid;
}
/*
тили, тили, трали-вали: создали, вызвали
*/
MainWindow::~MainWindow(
  delete wid;
)

Это я пробовал, но не помогло.

В случае создания activeX в конструкторе деструктор нормально вызывается, и объект уничтожается.
А если я делаю создание activeX через слот, то при закрытии главного окна деструктор вообще не вызывается.
Тогда я ставлю setAttribute(Qt::WA_DeleteOnClose); главному окну и тогда программа просто грохается.
Записан
kirill
Гость
« Ответ #11 : Май 06, 2010, 15:15 »

Кинул минимальный пример кода с проектами.
ActiveQtServer - сервер
ActiveQtClient - клиент

Записан
Sanya
Гость
« Ответ #12 : Май 06, 2010, 15:47 »

Я правильно понял, просто вызывать второй слот где делается delete wid пробовал, но не помогло?
Записан
kirill
Гость
« Ответ #13 : Май 06, 2010, 17:22 »

Я правильно понял, просто вызывать второй слот где делается delete wid пробовал, но не помогло?
Да да, во втором слоте вручную удаляю, но не помогает. Деструктор MainWindow не вызывается.
Записан
BRE
Гость
« Ответ #14 : Май 06, 2010, 17:54 »

Деструктор MainWindow не вызывается.
Так проблема в том, что не вызывается деструктор MainWindow?
А если "руками" удалить объект QAxWidget, то все нормально выгружается?
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.147 секунд. Запросов: 20.