Russian Qt Forum

Программирование => С/C++ => Тема начата: Bepec от Апрель 27, 2012, 12:48



Название: DLL. Простые вопросы по изъеженной теме.
Отправлено: Bepec от Апрель 27, 2012, 12:48
Уважаемые знатоки, приветствую.

Понадобилось неожиданно мне проникнуться мудростью создания dll  и внедрения в них добрых функций и классов.
Почитал я форум. Не понял. Почитал темы. Не понял. Почитал ещё. Не понял.

Собственно вопросы:
  • Есть 2 типа dll (статические(lib), динамические(dll)). Но получается, для подключения каждого типа, необходим h файл, подключенный к проекту?
    Что вообще для этого подключения надо (в моём мозгу создавалось впечатление, что достаточно одной dll...)
  • Создание класса из dll. Не нашёл нормального примера, или пояснения (облом у меня в знаниях Оо)
  • Чтобы создать класс, объявленный в dll, необходимо сначала создать указатель на этот класс. Как и откуда его получить? (получается из h файла чтоли?)   
  • И ЧЯДНТ в нижеприведённом проекте?

dll.cpp
Код:
#include "tstdll.h"

tstDll::tstDll()
{
   
}

tstDll::~tstDll()
{

}

void tstDll::dd()
{
    QWidget *k = new QWidget(0);
    k->show();
    k->setStyleSheet("background-color:red;");

}
dll.h
Код:
#ifndef TSTDLL_H
#define TSTDLL_H

#include "tstdll_global.h"
#include <QWidget>


 extern "C" class TSTDLL_EXPORT tstDll
{
public:
    tstDll();
    ~tstDll();
    void dd();
private:

};

#endif // TSTDLL_H
program.cpp
Код:
#include "tstdllload.h"

tstDllLoad::tstDllLoad(QWidget *parent, Qt::WFlags flags)
    : QWidget(parent, flags)
{
    ui.setupUi(this);
    myLib.setFileName("tstDll");
    bool b = myLib.load();
    typedef tstDll (*dd)();
    dd myFunction = (dd) myLib.resolve("tstDll");
    if (myFunction)
        myFunction();
}

tstDllLoad::~tstDllLoad()
{

}
program.h
Код:
#ifndef TSTDLLLOAD_H
#define TSTDLLLOAD_H

#include <QtGui/QWidget>
#include "ui_tstdllload.h"
#include <QLibrary>

class tstDllLoad : public QWidget
{
    Q_OBJECT

public:
    tstDllLoad(QWidget *parent = 0, Qt::WFlags flags = 0);
    ~tstDllLoad();

private:
    Ui::tstDllLoadClass ui;
    QLibrary myLib;
};

#endif // TSTDLLLOAD_H


Название: Re: DLL. Простые вопросы по изъеженной теме.
Отправлено: alexis031182 от Апрель 27, 2012, 13:39
Есть 2 типа dll (статические(lib), динамические(dll)). Но получается, для подключения каждого типа, необходим h файл, подключенный к проекту?
Для динамически подключаемых не обязателен.

Что вообще для этого подключения надо (в моём мозгу создавалось впечатление, что достаточно одной dll...)
Для динамически подключаемых - да.

Создание класса из dll. Не нашёл нормального примера, или пояснения (облом у меня в знаниях Оо)
Если требуется подключение произвольного (не библиотечного, вроде QObject или QWidget) класса из dll, то заголовочный файл потребуется присоединить к проекту. Лучше всего в нём объявить интерфейс (виртуальный класс), от которого в dll-ке унаследовать экспортируемый. Для примера можно посмотреть Plug&Paint (http://qt-project.org/doc/qt-4.8/tools-plugandpaint.html).

Чтобы создать класс, объявленный в dll, необходимо сначала создать указатель на этот класс. Как и откуда его получить? (получается из h файла чтоли?)
В этом случае в dll-ке должна быть экспортируемая функция, которая будет создавать и возвращать новый объект класса.

И ЧЯДНТ в нижеприведённом проекте?
Функция dd должна быть вне класса, и именно её надо экспортировать.


Название: Re: DLL. Простые вопросы по изъеженной теме.
Отправлено: Kurles от Апрель 27, 2012, 13:46
Код
C++ (Qt)
  myLib.setFileName("tstDll");
   bool b = myLib.load();
   typedef tstDll (*dd)();
   dd myFunction = (dd) myLib.resolve("tstDll");
   if (myFunction)
   myFunction();
Ты пытаешься вытащить из tstDll.dll (tstDll.so) глобальную функцию tstDll tstDll(), которой у тебя нет. Через
Код
C++ (Qt)
void* QLibrary::resolve (const char *symbol)
можно вытаскивать только С функции. Хочешь вытащить какой-нибудь класс - нужно объявить в подключаемой библиотеке функцию, которая будет возвращать пустой указатель на нужный класс.
Код
C++ (Qt)
void* getMyClass(int param);
а затем приводить уже к нужному классу и использовать.


Название: Re: DLL. Простые вопросы по изъеженной теме.
Отправлено: Bepec от Апрель 27, 2012, 14:07
Цитировать
Цитировать
Чтобы создать класс, объявленный в dll, необходимо сначала создать указатель на этот класс. Как и откуда его получить? (получается из h файла чтоли?)
В этом случае в dll-ке должна быть экспортируемая функция, которая будет создавать и возвращать новый объект класса.
Не осознал - для её получения, необходимо создать указатель этого класса. Дабы получить доступ к его методам. Но откуда его взять???

Проще:
Код:
void * func = <какая то функция>
// а далее надо получить тип класса, допустим  "tstDll", но его то я незнаю. Откуда его взять?
<???>tstDll</???> * funcDll = *func;

Принцип с классами в принципе ясен (получается как раз плагин), т.е. все классы находящиеся в dll должны быть наследниками 1 класса, который определён в программе и она его знает(может привести)

Но собственно ещё вопрос: Возможно ли создать самостоятельную dll ?

То есть не использовать его функции, а запустить её исполнение. Допустим спрятать в dll виджет с видео.


И таки ещё вопрос: Как можно из dll (исполняемой как раз), обмениваться информацией с другими процессами (и не Qt тоже)? (Вроде думается, что только пайпами (OS Windows)) ?


И ещё вопрос. Есть ли возможность именно создавать самостоятельные dll? К примеру 5 элементов - проигрыватель, панель, эффекты. Которые являтьяс будут разными dll, общающиеся между собой через *** (возможно пайпы).


Название: Re: DLL. Простые вопросы по изъеженной теме.
Отправлено: alexis031182 от Апрель 27, 2012, 14:26
Не осознал - для её получения, необходимо создать указатель этого класса. Дабы получить доступ к его методам. Но откуда его взять???
Например, если это будет указатель на QObject, то *.h не нужен. Но в то же время, если возвращаемый из dll-ки класс унаследован от QObject (или вообще произвольный), то в этом случае без объявления такого класса в коде проекта не обойтись.

Если необходимо избавиться от *.h, то можно попробовать поступить так: из dll-ки возвращать QObject, а затем, через QMetaObject получать список методов класса.

Проще:
Код:
void * func = <какая то функция>
// а далее надо получить тип класса, допустим  "tstDll", но его то я незнаю. Откуда его взять?
<???>tstDll</???> * funcDll = *func;
В этом случае без *.h не обойтись.

Принцип с классами в принципе ясен (получается как раз плагин), т.е. все классы находящиеся в dll должны быть наследниками 1 класса, который определён в программе и она его знает(может привести)
Да, плагины этот принцип и используют. Только наследуется от интерфейса как правило лишь один класс в dll-ке, он как точка соприкосновения.

Но собственно ещё вопрос: Возможно ли создать самостоятельную dll ?
То есть не использовать его функции, а запустить её исполнение. Допустим спрятать в dll виджет с видео.
Если dll-ка самодостаточна, и ей не требуется взаимодействовать с загрузившим её приложением, то по идее достаточно одной экспортируемой функции.


Название: Re: DLL. Простые вопросы по изъеженной теме.
Отправлено: Bepec от Апрель 27, 2012, 14:33
Не могли бы вы привести пример "автономной" dll с одной экспортируемой функцией?



Название: Re: DLL. Простые вопросы по изъеженной теме.
Отправлено: alexis031182 от Апрель 27, 2012, 15:12
START DLL PROJECT

dll.h
Код:
#ifndef DLL_H
#define DLL_H

#include <QObject>

#ifdef Q_WS_WIN
 #define MY_EXPORT __declspec(dllexport)
 #else
 #define MY_EXPORT
 #endif

extern "C" MY_EXPORT QObject *getObj();

#endif // DLL_H

dll.cpp
Код:
#include "dll.h"
#include <QDebug>

QObject *getObj()
{
QObject *obj = new QObject();
obj->setObjectName("tra-ta-ta");
qDebug() << "OK from DLL" << endl;
return obj;
}

END DLL PROJECT

START MAIN PROJECT

main.cpp
Код:
#include <QtCore/QCoreApplication>
#include <QLibrary>
#include <QDebug>

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

QLibrary lib("filname.dll");
typedef QObject* (*MyPrototype)();
MyPrototype myFunction = (MyPrototype)lib.resolve("getObj");
if(myFunction) {
   QObject *obj = myFunction();
   qDebug() << obj->objectName() << endl;
}

return a.exec();
}
END MAIN PROJECT


Название: Re: DLL. Простые вопросы по изъеженной теме.
Отправлено: Kurles от Апрель 27, 2012, 15:37
Не могли бы вы привести пример "автономной" dll с одной экспортируемой функцией?
Уже ответили, но продублирую


Название: Re: DLL. Простые вопросы по изъеженной теме.
Отправлено: Bepec от Апрель 27, 2012, 15:44
Благодарю за рабочий пример, очень помогли понять.

Следующий вопросик, точнее даже утверждение - в Дллке можно спокойно работать с классами и прочим.
Но. Но. Если дллку подключить к C/C++ чистому проекту, то при наличии необходимых библиотек логика dll отработает? (Qtшная?)

Проще говоря - будет ли работать программа, написанная на Qt, при наличии необходимых библиотек, вызванная из С/С++ чистой программы?

PS ну и грабли показывайте.


Название: Re: DLL. Простые вопросы по изъеженной теме.
Отправлено: V1KT0P от Апрель 27, 2012, 15:47
Благодарю за рабочий пример, очень помогли понять.

Следующий вопросик, точнее даже утверждение - в Дллке можно спокойно работать с классами и прочим.
Но. Но. Если дллку подключить к C/C++ чистому проекту, то при наличии необходимых библиотек логика dll отработает? (Qtшная?)

Проще говоря - будет ли работать программа, написанная на Qt, при наличии необходимых библиотек, вызванная из С/С++ чистой программы?

PS ну и грабли показывайте.

Я пихал графический виджет в С библиотеку, вызывал функции, грабил изображения и отдавал по запросу. Работает стабильно =).


Название: Re: DLL. Простые вопросы по изъеженной теме.
Отправлено: alexis031182 от Апрель 27, 2012, 15:55
Благодарю за рабочий пример, очень помогли понять.
Я вдруг подумал, что это была проверка. Как в анекдоте про невидимого суслика :)

Следующий вопросик, точнее даже утверждение - в Дллке можно спокойно работать с классами и прочим.
Но. Но. Если дллку подключить к C/C++ чистому проекту, то при наличии необходимых библиотек логика dll отработает? (Qtшная?)

Проще говоря - будет ли работать программа, написанная на Qt, при наличии необходимых библиотек, вызванная из С/С++ чистой программы?

PS ну и грабли показывайте.
Честно говоря, не могу утверждать на 100%, поскольку самолично такого не делал, но логика подсказывает, что всё будет в порядке. При минимуме взаимодействия (да даже и с полной интеграцией при должном внимании к коду) Qt-dll-ка будет работать как ей предписано.

Про грабли... может быть кто-нибудь ещё подскажет, реальны ли они в указанной ситуации в принципе.


Название: Re: DLL. Простые вопросы по изъеженной теме.
Отправлено: Igors от Апрель 27, 2012, 16:17
Проще говоря - будет ли работать программа, написанная на Qt, при наличии необходимых библиотек, вызванная из С/С++ чистой программы?
Будет но толку от этого немного, т.к. из чистого хоста ни передать ни принять Qt объекты нельзя (ну разве как-то через void *)

А вот такое дело (никогда не понимал)
Код
C++ (Qt)
// export ф-ция MyLib.dll
 
int * GetData( void )
{
static int data;
return &data;
}
 
Теперь 2 разных хоста загрузили MyLib.dll. Что будет с данными на которые указывает data?


Название: Re: DLL. Простые вопросы по изъеженной теме.
Отправлено: alexis031182 от Апрель 27, 2012, 16:25
Будет но толку от этого немного, т.к. из чистого хоста ни передать ни принять Qt объекты нельзя (ну разве как-то через void *)
Но речь ведь об этом и шла, чтобы минимум взаимодействия.

А вот такое дело (никогда не понимал)
...
Теперь 2 разных хоста загрузили MyLib.dll. Что будет с данными на которые указывает data?
Не будет работать? Похоже на... э-э-э... синглтон в dll-ке.


Название: Re: DLL. Простые вопросы по изъеженной теме.
Отправлено: Bepec от Апрель 27, 2012, 16:53
Нет, это не проверка (по секрету скажу  - [вырезано из соображений секретности] и конечно [вырезано из соображений секретности]).

Поняяяятненько. Далее вопросы конечно появятся, но не сегодня- завтра. Спасибо за отклик.


Название: Re: DLL. Простые вопросы по изъеженной теме.
Отправлено: alexis031182 от Апрель 27, 2012, 17:46
Нет, это не проверка (по секрету скажу  - [вырезано из соображений секретности] и конечно [вырезано из соображений секретности]).
)))) Да, я уже заметил, сколько секретно-правительственных (http://www.prog.org.ru/index.php?topic=21761.msg151455#msg151455) разрабов на этом форуме шифруется


Название: Re: DLL. Простые вопросы по изъеженной теме.
Отправлено: V1KT0P от Апрель 27, 2012, 18:13
Про грабли... может быть кто-нибудь ещё подскажет, реальны ли они в указанной ситуации в принципе.
Ну один момент помню. У меня библиотека видела память выделенная программой, а программа не видела память выделенную библиотекой. И для получения изображения пришлось в программе выделять память, отдавать ее библиотеке и она уже ее наполняла. При попытке выделить память под изображение в библиотеке падала.
Конечно может я что-то начудил...