crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Классы в динамических библиотеках.
MishaUA
  опции профиля:
сообщение 3.4.2014, 17:48
Сообщение #1


Участник
**

Группа: Участник
Сообщений: 185
Регистрация: 28.4.2013
Пользователь №: 3810

Спасибо сказали: 13 раз(а)




Репутация:   0  


Добрый день! Настал час, когда пришлось писать динамические библиотеки.
В проге через QLibrary подключается библиотека и далее используются ее функции.
В коде самой dll содержится класс, методы которого нужно вызывать, но в отличии от статической библиотеки, в динамической методы вызывать нельзя, только функции, Я поступил следующим образом:
class MyLib
{
public:
    MyLib();

    QString Test() {return "Hello!";};
};

MyLib    lblb;    // создаем класс

extern "C" {
QString Test() {return lblb.Test();}
}

Является ли такой вариант правильным, или посоветуете что то получше?
И еще интересует, как с библиотеки можно передать сигнал в программу?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
arial
  опции профиля:
сообщение 3.4.2014, 19:33
Сообщение #2


Студент
*

Группа: Участник
Сообщений: 39
Регистрация: 27.9.2009
Пользователь №: 1121

Спасибо сказали: 9 раз(а)




Репутация:   0  


А QtPlugin разве не удобнее использовать?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
MishaUA
  опции профиля:
сообщение 3.4.2014, 20:36
Сообщение #3


Участник
**

Группа: Участник
Сообщений: 185
Регистрация: 28.4.2013
Пользователь №: 3810

Спасибо сказали: 13 раз(а)




Репутация:   0  


И еще, хочу в программе отображать виджет, созданный в библиотеке (библиотека должна им управлять, реагировать на сигналы и т.д.), программа только отображать. Сделал так:
*.h библиотеки:
extern "C" {
QString Test();
QWidget *widget();
}

class MyLib : public QObject
{
    Q_OBJECT
public:
    MyLib();

    struct {
        QLabel    *label;
        QPushButton    *button;
    } w;

    QWidget    *widget;

private slots:
    void tim();
};

*.cpp библиотеки:
MyLib    lb;    // создаем класс

QString Test(){return lb.Test();}
QWidget *widget() {return lb.widget;}

MyLib::MyLib()
{
    qDebug() << "MyLib";

    widget = new QWidget();
    widget->setLayout(new QVBoxLayout);

    widget->layout()->addWidget(w.label = new QLabel());
    widget->layout()->addWidget(w.button = new QPushButton("Update"));
    connect(w.button, SIGNAL(clicked()), this, SLOT(tim()));
}

void MyLib::tim()
{
    w.label->setText(QDateTime::currentDateTime().toString());
}

*.cpp программы:
    QLibrary    *lib = new QLibrary("d:/MyLib1.dll", this);
    qDebug() << lib->load();

    typedef QWidget* (*Fct) ();
    Fct    fct = (Fct)(lib->resolve("widget"));
    QWidget    *w = fct();
    ui->tabWidget->addTab(w, "dgdg");

Работает нормально, единственная проблема - если добавлять виджет не на таб, а к примеру, в компоновщик главного окна, то программа не реагирует на мышь (ни контролы виджета библиотеки, ни контролы, созданые в программе). Но предполагается, что в реальной программе будет именно создаваться новый таб.
Чтобы не накосячить, хочу поинтересоваться, на сколько правильное мое решение?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
MishaUA
  опции профиля:
сообщение 4.4.2014, 0:30
Сообщение #4


Участник
**

Группа: Участник
Сообщений: 185
Регистрация: 28.4.2013
Пользователь №: 3810

Спасибо сказали: 13 раз(а)




Репутация:   0  


arial, Есть вероятность, что dll будут собираться иными компиляторами (использование виджетов будет не обязательным), поэтому я и предположил, что их выгодней использовать))))
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.4.2014, 18:22
Сообщение #5


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9656
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


class MyLib : public QObject
MishaUA, не вижу у тебя инициализации структуры w

А вообще сделай функцию, которая будет создавать экземпляр (объект), а дальше работай с ним как обычно.

class MyWidget : public QWidget
{
public:
    MyWidget (arg1, arg2, ...);

}

MyWidget* creatMyWidget(arg1, arg2, ...)
{
    return new MyWidget(arg1, arg2, ...)
}

    QLibrary    *lib = new QLibrary("d:/MyLib1.dll", this);
    qDebug() << lib->load();

    typedef QWidget* (*CreatMyWidget) ();
    CreatMyWidget    creatMyWidget = (CreatMyWidget)(lib->resolve("widget"));
    QWidget    *w = creatMyWidget();
    ...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 6.4.2014, 12:36
Сообщение #6


Профессионал
*****

Группа: Модератор
Сообщений: 1587
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 218 раз(а)




Репутация:   12  


да, выше Юрий правильно заметил, что работа с классами есть самое обычное дело. экспортируется весь класс и проблем нет. более того, можно даже наследоваться от классов, объявленных в других библиотеках. я тут где-то про такой случай писала.
единственная возможная проблема - это не будет работать с разными компиляторами. то есть, если основная программа скомпилена одним компилятором, а библиотеки - другим. а у мелкософта иногда даже разные версии компиляторов не совместимы. так что тут надо понимать, как это потом будет эксплуатироваться. если предполагается, что другие программисты будут собирать какие-то внешние модули, то получится ограничение на выбор компилятора.
и ещё видимость классов у GCC и MSVC разная. но обычно это не представляет проблемы.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
MishaUA
  опции профиля:
сообщение 6.4.2014, 23:30
Сообщение #7


Участник
**

Группа: Участник
Сообщений: 185
Регистрация: 28.4.2013
Пользователь №: 3810

Спасибо сказали: 13 раз(а)




Репутация:   0  


Спасибо за ответы!
Еще интересует, при загрузке библиотеки она будет работать в том же потоке программы, в котором она была загружена?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 7.4.2014, 8:32
Сообщение #8


Профессионал
*****

Группа: Модератор
Сообщений: 1587
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 218 раз(а)




Репутация:   12  


во всех потоках. у потоков общая память. то есть, как обычный класс, определённый в программе.
если в библиотеке есть статические переменные - они будут статическими и общими для всех потоков.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 8.4.2014, 18:27
Сообщение #9


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9656
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Тут правильнее речь вести об объекте (экземпляре класса). В каком потоке ты его создаёшь, в том он и будет жить.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 8.4.2014, 20:34
Сообщение #10


Профессионал
*****

Группа: Модератор
Сообщений: 1587
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 218 раз(а)




Репутация:   12  


Цитата(Litkevich Yuriy @ 8.4.2014, 21:27) *
Тут правильнее речь вести об объекте (экземпляре класса). В каком потоке ты его создаёшь, в том он и будет жить.

не совсем так. память в куче у потоков общая. а стек у каждого свой.
как бы явно к локальным переменным потока доступа нет, но в линюксе если взять адрес, то пока переменная валидна, она будет доступна по этому адресу во всех других потоках (см документацию на GCC, статью о TLS).
в венде чуть сложнее - там индексы областей TLS. но есть функция TlsSetValue и другие функции из этой же серии (также гуглить про TLS, если интересно).

Сообщение отредактировал Iron Bug - 8.4.2014, 20:56
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 18.10.2019, 2:51