C++: Динамично загружающиеся классы от dlls

Я рекомендую:

if ([[[UIDevice currentDevice] systemVersion] floatValue] > 3.13) {
    ; // ...
}

credit: Как настроить таргетинг на определенную версию iPhone?

22
задан Fire Lancer 10 January 2009 в 19:27
поделиться

4 ответа

Самый легкий способ сделать это, по моему скромному мнению, должно иметь простую функцию C, которая возвращает указатель на интерфейс, описанный в другое место. Тогда Ваше приложение, может вызвать все функции того интерфейса, на самом деле не зная, какой класс это использует.

Редактирование: вот простой пример.

В Вашем коде главного приложения, Вы создаете заголовок для интерфейса:

class IModule
{
public:
    virtual ~IModule(); // <= important!
    virtual void doStuff() = 0;
};

Главное приложение кодируется для использования интерфейса выше без любых деталей о фактической реализации интерфейса.

class ActualModule: public IModule
{
/* implementation */
};

Теперь, модули - DLL имеет фактическую реализацию того интерфейса, и те классы не должны даже быть экспортированы - __declspec (dllexport), не необходим. Единственное требование для модулей должно экспортировать единственную функцию, которая создала бы и возвратила бы реализацию интерфейса:

__declspec (dllexport) IModule* CreateModule()
{
    // call the constructor of the actual implementation
    IModule * module = new ActualModule();
    // return the created function
    return module;
}

примечание: проверка ошибок не учла - Вы обычно хотели бы проверить, если бы новый возвратил корректный указатель, и необходимо защитить себя от исключений, которые могли бы быть выданы в конструкторе ActualModule класс.

Затем в Вашем главном приложении, все, в чем Вы нуждаетесь, должно просто загрузить модуль (LoadLibrary функция) и найти функцию CreateModule (GetProcAddr функция). Затем Вы используете класс через интерфейс.

Редактирование 2: Ваш RefCount (базовый класс интерфейса), может быть реализован в (и экспортирован из), главное приложение. Тогда весь Ваш модуль должен был бы связаться с библиотечным файлом главного приложения (да! EXE-файлы могут иметь Библиотечные файлы точно так же, как файлы DLL!) И это должно быть достаточно.

21
ответ дан Paulius 29 November 2019 в 01:55
поделиться

Вы перестраиваете COM. Ваш класс RefCounted является IUnknown. Ваш абстрактный класс является интерфейсом. Сервер COM в DLL имеет entrypoint под названием DllGetClassObject (), это - фабрика классов. Существует много документации, доступной от Microsoft на COM, введите по абсолютному адресу вокруг немного, чтобы видеть, как они сделали это.

16
ответ дан Hans Passant 29 November 2019 в 01:55
поделиться

[Редактирование: пока я составлял все это, Paulius MaruЕЎka отредактировал его комментарий для высказывания в основном того же. Так извинения за любое дублирование. Хотя я предполагаю, что Вы теперь добрались один для запчасти:)]

Первое, что пришло на ум, и принимающий Visual C++...

необходимо использовать LoadLibrary, чтобы загрузить DLL в динамично, затем использовать GetProcAddress для получения от него адреса функции, которая создаст фактический производный класс, который реализует код DLL. Как Вы решаете сделать, это точно ваше дело (открытие потребности DLLs, способ, которым для представления их функциональности нужно определение, и т.д.) поэтому на данный момент позволяют нам предположить, что плагины только обеспечивают новые реализации Sprite.

, Чтобы сделать это, выберите подпись функции в DLL, который основная программа назовет для создания одного из этих новых спрайтов. Эти подходящие взгляды:

typedef Sprite *(*CreateSpriteFn)();

Затем из основной программы, необходимо будет загрузить DLL (снова, как Вы находите, что этот DLL ваше дело), и получите функцию создания спрайта от него. Я решил, что функция создания спрайта будет вызвана "CreateSprite":

HMODULE hDLL=LoadLibrary(pDLLName);
CreateSpriteFn pfnCreateSprite=CreateSpriteFn(GetProcAddress(hDLL,"CreateSprite"));

Затем для фактического создания одного из них просто вызовите функцию:

Sprite *pSprite=(*pfnCreateSprite)();

, Как только Вы сделаны с DLL и нет никаких объектов, оставленных, которые были созданы им, Вы тогда используете FreeLibrary для избавлений от него:

FreeLibrary(hDLL);

Для создания DLL, который щеголяет этим интерфейсом запишите, что код для производного класса и так далее тогда где-нибудь в коде DLL обеспечивает функцию CreateSprite, в которой программа вызова нужна, с помощью соответствующей подписи:

__declspec(dllexport)
extern "C"
Sprite *CreateSprite()
{
    return new MyNewSprite;
}

dllexport вещь означает, что можно использовать GetProcAddress для собирания этой функции по имени, и экстерн "C" удостоверяется, что имя не искажается и не заканчивается как "CreateSprite@4" или что-то как.

Два других примечания:

  1. GetProcAddress возвращается 0, если он не мог бы найти функцию, таким образом, можно использовать это для сканирования через список DLLs (например, возвращенные из FindFirstFile и друзей) ищущий DLLs, которые поддерживают интерфейс и/или пытаются найти многократные точки и поддерживать несколько типов на плагин.
  2. , если основная программа собирается удалить спрайт с помощью оператора delete, это требует, чтобы и DLL и основная программа были созданы, пользуясь той же библиотекой времени выполнения, так, чтобы основная программа удалила, и новый DLL оба используют ту же "кучу". Можно работать вокруг этого в некоторой степени при наличии DLL, обеспечивают функцию DeleteSprite, которая удаляет спрайт, пользующийся библиотекой времени выполнения DLL, а не основная программа, но все еще необходимо заботиться об остальной части программы, таким образом, можно просто хотеть вынудить писателей DLL пользоваться той же библиотекой времени выполнения как программа. (Я не сказал бы, что Вы будете в хорошей компании путем выполнения этого, но это весьма распространено. 3D Studio МАКС требует этого, например.)
4
ответ дан 29 November 2019 в 01:55
поделиться

Возможно, Вы хотите изучить Загрузку Задержки DLL ( http://www.codeproject.com/KB/DLL/Delay_Loading_Dll.aspx ) - это даст Вам, что Вы хотите, не имея необходимость также упорно работать для нее

2
ответ дан Ana Betts 29 November 2019 в 01:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: