Как я могу координировать различные DLL в одном процессе, без помощи со стороны хост-программы? - PullRequest
1 голос
/ 24 августа 2011

Я ищу способ координировать библиотеки DLL в одном и том же процессе, чтобы обеспечить механизм обмена данными между ними.Цель состоит в том, чтобы иметь один и тот же код общего доступа для всех библиотек DLL, и чтобы они координировались таким образом, чтобы первый, загруженный основной программой, действовал в качестве менеджера для общих элементов, в то время как другие будут использовать этот менеджер.Я не могу изменить основное приложение, поэтому невозможно настроить диспетчер и разделить его адрес памяти с другими библиотеками DLL.Набор библиотек DLL, использующих этот механизм, может варьироваться, поэтому я не могу явно предположить, что одна из них будет загружена.

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

Это близко к тому, что я хочу, но кажется немного грубым, поскольку нет никакой гарантии, что переменная окружения не 'установить по какой-либо причине, и SetEnvironmentVariable / GetEnvironmentVariable может завершиться ошибкой по разным причинам.

Есть ли лучший способ справиться с этим?Я ищу способ хранения и получения именованного указателя в контексте процесса, но если у вас есть лучшее решение для основной проблемы взаимодействия библиотек DLL, я был бы рад принять это.

Ответы [ 3 ]

2 голосов
/ 24 августа 2011

как насчет создания именованной общей памяти ?

, который позволит вам совместно использовать часть памяти, без хлопот получения адреса, действительного в контексте процесса.первая загруженная DLL создает разделяемую память, затем следующая DLL может напрямую обращаться к памяти, поверх которой вы можете создать свой собственный API обмена сообщениями.

1 голос
/ 24 августа 2011

Объедините GetModuleHandle() с GetProcAddress() для достижения этой цели.Зависимые DLL получат дескриптор к DLL менеджера, а затем используют GetProcAddress() для извлечения указателей из экспортируемых символов.

Или просто динамически связывают зависимые DLL с DLL менеджера и используют файл заголовкадля внешних определений.


Я неправильно понял ваш вопрос;однако вышеупомянутый подход все еще может быть полезен.

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

Этот метод чреват гоночными условиями, если эти модули могут быть инициализированы одновременно.Было бы лучше иметь один модуль супервизора, который каждый модуль может использовать в качестве точки связи.

0 голосов
/ 24 августа 2011

cdhowie приводит несколько веских причин, почему это плохая идея.

Однако, если вы действительно хотите это сделать, не загрязняя глобальное пространство имен совместно используемой памяти: зарегистрируйте класс окна в вашей точке входа DLL, но передайте экземпляр EXE-файла как поле hInstance класса окна.

Каждая DLL может проверить, зарегистрирован ли класс; если нет, зарегистрируйтесь. Первая DLL, успешно зарегистрировавшая класс окна, становится главной. Чтобы получить указатель на некоторую структуру, инициализированную мастером в впоследствии загруженных DLL, затем создайте окно этого класса только для сообщений и используйте SendMessage для вызова его оконной процедуры (в главной DLL).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...