Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 24, средняя оценка - 4.92
kpoxa
5 / 5 / 0
Регистрация: 08.12.2009
Сообщений: 213
#1

Определение класса в DLL - ипользование вне и динамически - C++

06.10.2006, 21:45. Просмотров 2914. Ответов 6
Метки нет (Все метки)

Однажды я уже задавал подобный ворос, ответа так и не получил. В свое время я обошелся без использования классов из DLL, но сейчас вновь возникла необходимость и обойтись не получится.
Скажем в DLL есть такой код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <windows.h>
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
class DLL_API CMyDllObject{
public:
 CMyDllObject(void);
 void Say(LPSTR msg) ;
};
 
CMyDllObject::CMyDllObject()
{
}
void CMyDllObject::Say(LPSTR msg)
{
    MessageBox(0, msg, "My DLL",0);
}
extern "C" DLL_API CMyDllObject* CreateMyObject()
{
    return new CMyDllObject();
} 
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
      )
{
    switch (ul_reason_for_call)
 {
  case DLL_PROCESS_ATTACH:
  case DLL_THREAD_ATTACH:
  case DLL_THREAD_DETACH:
  case DLL_PROCESS_DETACH:
   break;
    }
    return TRUE;
}
Конечно декларацию класса можно перенести и в отдельный файл, но на данный момент это не имеет отношения к делу.
Мне надо в основном проекте создать объект класса CMyDllObject, при этом статическое линкование не подходит, так как я не знаю какую DLL буду загружать (есть несколько одинаковых по функциональности, но действие разное). Пользователь выбирает, что будет использоваться в данный момент.
Код будет выглядеть примерно так (как именно - это как раз и является вопросом)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <windows.h>
class __declspec(dllexport) CMyDllObject{
public:
 CMyDllObject(void);
 void Say(LPSTR msg) ;
};
int main(int argc, char* argv[])
{
 HMODULE hDll ;
 
 hDll = LoadLibrary("MyDll.dll") ;
 if(hDll) {
  typedef CMyDllObject* (* F_CREATE)() ;
  F_CREATE CreateMyObject = 0 ;
  CreateMyObject = (F_CEATE)GetProcAddress(hDll, "CreateMyObject") ;
  if(CreateMyObject) {
      CMyDllObject * pObj = 0 ;
      pObj = CreateMyObject();
      if(pObj)  pObj->Say("Hello");
  }
  FreeLibrary(hDll);
 }
 return 0;
}
Приведенный здесь код не работает. В основном проекте у класса нет имплементации.
Мне не хотелось бы создавать ActiveX или COM библиотеку, так как их надо регестрировать в системе, а мне надо подгружать недостающии библиотеки с другого компьютера во время выполнения и удалять ненужные. Кроме того я не использую в проекте MFC, только Win API.
Подскажите, пожалуйста, как мне решить поставленную задачу?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.10.2006, 21:45     Определение класса в DLL - ипользование вне и динамически
Посмотрите здесь:

C++ Перегрузка оператора ввода вне класса
Как создать DLL в VS2010 C++ Динамически подключаемую? C++
C++ Определение метода вне класса, как inline в многофайловом проекте
C++ Перегрузка оператора '+' для char* вне класса
Определить функции итератора, вне класса C++
C++ Функция вне класса для передачи функции объекта
C++ Определение методов вне класса
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
kpoxa
5 / 5 / 0
Регистрация: 08.12.2009
Сообщений: 213
15.10.2006, 21:37  [ТС]     Определение класса в DLL - ипользование вне и динамически #2
Никак не пойму, неужели вопрос на столько сложен, что некому не него ответитЬ? Или может вопрос поставлен не совсем понятно? Скажите, попробую разъяснить.
Вообще складывается впечатление, что в последнее время на этот форум очень мало кто заходит. Если это так, то очень жаль, не плохой был форум (по крайней мере год назад).
Я думаю что boombastik, bazile или messir вполне в состоянии были бы дать ответ на мой вопрос, или я ошибаюсь?
bazile
58 / 34 / 19
Регистрация: 15.03.2007
Сообщений: 6,911
16.10.2006, 00:08     Определение класса в DLL - ипользование вне и динамически #3
Я думаю что boombastik, bazile или messir вполне в состоянии были бы дать ответ на мой вопрос, или я ошибаюсь?
Я не считаю себя спецом по С++ и поэтому не стоит ожидать моих ответов в этом форуме. В данном же случае есть одна идея.
Код в DLL файле кроме класса должен содержать и одноименные функции из класса с дополнительный параметром указывающем на конкретный экземпляр (аналог this).
Код внутри DLL:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class DllObject
{
public:
    DllObject() { }
    void Say(LPCTSTR message) const
    {
        MessageBox(0, message, TEXT("My DLL"), MB_ICONINFORMATION | MB_OK);
    }
};
 
extern "C" __declspec(dllexport) DllObject* CreateObject()
{
    return new DllObject();
}
 
extern "C" __declspec(dllexport) void DestroyObject(DllObject* pimpl)
{
    if (pimpl)
    {
        delete pimpl;
    }
}
 
extern "C" __declspec(dllexport) void Say(DllObject* pimpl, LPCTSTR message)
{
    if (pimpl)
    {
        pimpl->Say(message);
    }
}
 
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    if (DLL_PROCESS_ATTACH == fdwReason)
    {
        DisableThreadLibraryCalls(hinstDLL);
    }
    return TRUE;
}
Функция CreateObject() создает объект и возвращает указатель на него. Этот указатель затем должен быть передан вызывающим кодом в функцию Say.
Код proxy класса:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class DllObjectProxy
{
private:
    // Запрет использования оператора присваивания и конструктора копирования
    DllObjectProxy(DllObjectProxy&) { }
    DllObjectProxy& operator=(DllObjectProxy&) { }
    typedef void* (*CREATE_OBJECT_PROC)();
    typedef void (*DESTROY_OBJECT_PROC)(void*);
    typedef void (*SAY_PROC)(void*, LPCTSTR);
    CREATE_OBJECT_PROC createObject_;
    DESTROY_OBJECT_PROC destroyObject_;
    HMODULE dllHandle_;
    void* pimpl_; // pointer to implementation
public:
    DllObjectProxy(LPCTSTR lpDllName);
    ~DllObjectProxy();
    void Say(LPCTSTR message) const;
};
 
DllObjectProxy::DllObjectProxy(LPCTSTR lpDllName)
{
    dllHandle_ = LoadLibrary(lpDllName);
    if (!dllHandle_)
    {
        // Ошибка загрузки DLL
        throw new ...;
    }
    createObject_  = reinterpret_cast<CREATE_OBJECT_PROC>(GetProcAddress(dllHandle_, "CreateObject"));
    destroyObject_ = reinterpret_cast<DESTROY_OBJECT_PROC>(GetProcAddress(dllHandle_, "DestroyObject"));
    if (!createObject_ || !destroyObject_)
    {
        // Нет функции создания/удаления класса
        // Неправильная DLL?
        FreeLibrary(dllHandle_);
        throw new ...;
 &
bazile
58 / 34 / 19
Регистрация: 15.03.2007
Сообщений: 6,911
16.10.2006, 14:41     Определение класса в DLL - ипользование вне и динамически #4
Внес небольшие изменения в код примера выше так как забыл добавить код удаления объекта из памяти.
kpoxa
5 / 5 / 0
Регистрация: 08.12.2009
Сообщений: 213
16.10.2006, 18:09  [ТС]     Определение класса в DLL - ипользование вне и динамически #5
Код выглядит интересно. Думаю его можно тоже вынести в DLL, но так как в этом случае будет только одна библиотека, то её можно будет добавить в проект для линковки. Это хорошо. Однако остаётся проблема дублирования всех фунций членов класса в оригинальной DLL (умножить на количество таких библиотек) плюс их дублирования в Proxy Dll.
А можно ли каким либо образом воспользоваться интерфейсами? Если честно, я ни разу не сталкивался с ними и не представляю, как с ними работают. Но идея видится мне заманчивой, определить интерфейс, слинковать его в основном проекте, а затем пользоваться вызовами, подобными обычному вызову функций объекта.
Можете ли вы дать линки на эту тему, где в простой форме описывается создание и работа с интерфейсами?
В любом случае, спасибо за пример Proxy, он достоин внимания.
bazile
58 / 34 / 19
Регистрация: 15.03.2007
Сообщений: 6,911
17.10.2006, 13:55     Определение класса в DLL - ипользование вне и динамически #6
kpoxa (16.10.2006)
Код выглядит интересно. Думаю его можно тоже вынести в DLL, но так как в этом случае будет только одна библиотека, то её можно будет добавить в проект для линковки. Это хорошо. Однако остаётся проблема дублирования всех фунций членов класса в оригинальной DLL (умножить на количество таких библиотек) плюс их дублирования в Proxy Dll.
Только не в dll, а скорее в lib. Proxy класс у тебя один для всех DLL. Ты же сам говорил, что классы имеют одинаковый интерфейс, но разную реализацию.
kpoxa (16.10.2006)
А можно ли каким либо образом воспользоваться интерфейсами? Если честно, я ни разу не сталкивался с ними и не представляю, как с ними работают. Но идея видится мне заманчивой, определить интерфейс, слинковать его в основном проекте, а затем пользоваться вызовами, подобными обычному вызову функций объекта.
Можете ли вы дать линки на эту тему, где в простой форме описывается создание и работа с интерфейсами?
Интерфейсы здесь хорошо бы вписались, но ведь в C++ нет интерфйесов. Ближайший аналог это абстрактные классы.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.10.2006, 20:05     Определение класса в DLL - ипользование вне и динамически
Еще ссылки по теме:

Как перегрузить операторы вне класса? C++
Как реализовать вне класса тело метода? C++
Вызов функции вне класса C++
C++ Как реализовать метод шаблона вне класса?
Ипользование класса stringstream C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
bazile
58 / 34 / 19
Регистрация: 15.03.2007
Сообщений: 6,911
17.10.2006, 20:05     Определение класса в DLL - ипользование вне и динамически #7
Проверил свой код на практике. Пример работает. В процессе внес небольшие изменения в код (смотрите уже исправленный текст выше)</P><UL><LI>Исправил синтаксические ошибки</LI><LI>Запретил оператор присваивания и конструктор копирования в классе DllObjectProxy.</LI><LI>Перенес typedef-ы в private часть класса DllObjectProxy, нет никакого смысла замусоривать глобальную область видимости подобными объявлениями.</LI><LI>Приведения типов в стиле С++ (reinterpret_cast<>)</LI></UL>
Вроде все. Главное было убедиться в работоспобности идеи.
Yandex
Объявления
17.10.2006, 20:05     Определение класса в DLL - ипользование вне и динамически
Ответ Создать тему
Опции темы

Текущее время: 00:49. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru