Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Классы в динамических библиотеках.
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Общие вопросы
MishaUA
Добрый день! Настал час, когда пришлось писать динамические библиотеки.
В проге через QLibrary подключается библиотека и далее используются ее функции.
В коде самой dll содержится класс, методы которого нужно вызывать, но в отличии от статической библиотеки, в динамической методы вызывать нельзя, только функции, Я поступил следующим образом:
class MyLib
{
public:
    MyLib();

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

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

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

Является ли такой вариант правильным, или посоветуете что то получше?
И еще интересует, как с библиотеки можно передать сигнал в программу?
arial
А QtPlugin разве не удобнее использовать?
MishaUA
И еще, хочу в программе отображать виджет, созданный в библиотеке (библиотека должна им управлять, реагировать на сигналы и т.д.), программа только отображать. Сделал так:
*.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
arial, Есть вероятность, что dll будут собираться иными компиляторами (использование виджетов будет не обязательным), поэтому я и предположил, что их выгодней использовать))))
Litkevich Yuriy
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
да, выше Юрий правильно заметил, что работа с классами есть самое обычное дело. экспортируется весь класс и проблем нет. более того, можно даже наследоваться от классов, объявленных в других библиотеках. я тут где-то про такой случай писала.
единственная возможная проблема - это не будет работать с разными компиляторами. то есть, если основная программа скомпилена одним компилятором, а библиотеки - другим. а у мелкософта иногда даже разные версии компиляторов не совместимы. так что тут надо понимать, как это потом будет эксплуатироваться. если предполагается, что другие программисты будут собирать какие-то внешние модули, то получится ограничение на выбор компилятора.
и ещё видимость классов у GCC и MSVC разная. но обычно это не представляет проблемы.
MishaUA
Спасибо за ответы!
Еще интересует, при загрузке библиотеки она будет работать в том же потоке программы, в котором она была загружена?
Iron Bug
во всех потоках. у потоков общая память. то есть, как обычный класс, определённый в программе.
если в библиотеке есть статические переменные - они будут статическими и общими для всех потоков.
Litkevich Yuriy
Тут правильнее речь вести об объекте (экземпляре класса). В каком потоке ты его создаёшь, в том он и будет жить.
Iron Bug
Цитата(Litkevich Yuriy @ 8.4.2014, 21:27) *
Тут правильнее речь вести об объекте (экземпляре класса). В каком потоке ты его создаёшь, в том он и будет жить.

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