Delphi Dynamic Dll - глобальная переменная - PullRequest
6 голосов
/ 25 июня 2009

Я занят кодированием dll, который предоставляет несколько функций хост-приложению. Это приложение вызывает dll динамически, загружая и освобождая его после каждого вызова функции.

У меня нет контроля над приложением хоста. Я могу работать только внутри DLL. Есть ли способ сохранить некоторые переменные в памяти, чтобы я мог повторно использовать их в каждой функции? Очевидно, что глобальный varable очищается, когда dll выгружается приложением хоста. Сохранение dll в файл звучит очень грязно!

Может кто-нибудь предложить способ присвоения переменной, которую я могу оставить глобальной?

Спасибо

Ответы [ 8 ]

4 голосов
/ 25 июня 2009

Я думаю, у вас есть 2 основных варианта.

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

  2. Сохраните состояние, как если бы вы где-то в файле (это было в основном то, что есть) в файле.

Вариант 1 потребует модификации хост-приложения, но для разработчиков хост-приложений будет необходимо использовать его, Вариант 2 не потребует никаких изменений в хост-приложении, но не будет столь же производительным.

Лично я не был бы склонен начинать копаться со счетчиком ссылок, вероятно, хост-приложение выгружается по причине, если бы я был разработчиком хост-приложения, это бы меня раздражало.

4 голосов
/ 25 июня 2009

Внимание, грязный хак:

Вы можете загрузить себя.

Каждый вызов LoadLibrary увеличивает счетчик ссылок, FreeLibrary уменьшает его. Только если счетчик достигает нуля, DLL выгружается.

Таким образом, если ваша библиотека DLL загружается в первый раз, вы просто загружаете библиотеку снова, увеличивая счетчик ссылок. Если вызывающее приложение вызывает FreeLibrary, счетчик ссылок уменьшается, но DLL не выгружается.

РЕДАКТИРОВАТЬ: Как указала mghi, DLL будет выгружена, если процесс завершится, независимо от того, равно ли число ссылок нулю.

2 голосов
/ 25 июня 2009

Другим решением, если у вас есть большой объем глобальных данных для совместного использования, было бы создание службы Windows для «кэширования» данных о состоянии. Вам также потребуется реализовать какой-либо IPC, который работает через границы процесса, например файлы с отображением в памяти, почтовые ящики, COM (один экземпляр для этого случая), TCP / IP и т. Д. Вы можете обнаружить, что эти издержки будут больше, чем просто запись состояния в файл, поэтому я рекомендую этот подход только в том случае, если объем данных о состоянии чрезмерен или будет рассматриваться только частями целого для каждого запроса в вашу dll.

Для COM-подхода сервис не должен делать ничего, кроме запроса (и удержания) экземпляра com-объекта, который вы будете использовать для поддержания состояния. Поскольку это один экземпляр com-объекта, все запросы будут к одному и тому же экземпляру, что позволит вам сохранять ваше состояние между запросами. Запросы к объекту сериализуются, поэтому это может быть проблемой производительности, если несколько клиентов запрашивают данные на одном и том же компьютере одновременно.

1 голос
/ 25 июня 2009

Лучший способ - использовать класс, содержащий «глобальные переменные». Вы создаете экземпляр объекта и передаете его в качестве параметра функциям dll. Но это не поможет вам, потому что вы не можете изменить вызывающее приложение.

Если вам нужно хранить глобальные данные в dll, решение - записать их в файл. Но это серьезно влияет на производительность.

0 голосов
/ 01 октября 2009

Это также может быть полезно

option 1: Создайте область разделяемой памяти, в которой ваши переменные будут подкреплены файлом подкачки - если вы можете открыть эту область совместно используемой памяти, ваша dll была предварительно загружена (предполагая «частное» имя разделяемой памяти, возможно, с именем типа process_id_yourdllname) - если вы можете не открывайте его, затем вы создаете и инициализируете его в первый раз. Если вы создадите его, то не потрудитесь удалить его - но если вы откроете его, вы закроете его - при выгрузке. Я полагаю, что эта область будет освобождена после закрытия приложения, поскольку никакие другие приложения не должны иметь дескрипторов для этой конкретной «частной» области общей памяти.

option 2: Создайте второй .dll, который существует только для управления глобальными переменными. Ваша dll A может загрузить эту dll B, а не освободить ее, поместив в dll B все, что вам нужно для управления глобальными переменными. Он должен исчезнуть, когда приложение исчезнет, ​​и я не думаю, что вам, вероятно, нужно заботиться о (предположительно бесполезном) подсчете ссылок (поскольку вы не будете выгружать dll B).

0 голосов
/ 25 июня 2009

Я согласен с предыдущими комментариями о том, что глобальная информация о состоянии опасна, хотя я могу представить, что она может понадобиться.

Я предлагаю более чистую версию грязного взлома DR, которая не имеет обратной стороны постоянства, как ответ Скамрадта:

Очень маленькое приложение:

У него нет внешнего вида, он не отображается на панели задач.

Задача № 1: Загрузить DLL

Задача № 2: Возьмите командную строку, запустите ее и дождитесь ее завершения.

Задача № 3: выгрузить DLL

Задание № 4: Выход.

Установщик:

Он находит ярлыки для основного приложения и изменяет их так, чтобы небольшое приложение запускалось, а исходное местоположение, на которое указывал ярлык, становится первым параметром.

Результаты: DLL остается в памяти только до тех пор, пока работает основное приложение, но не выгружается каждый раз, когда программа ее выгружает.

0 голосов
/ 25 июня 2009

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

-Аль.

0 голосов
/ 25 июня 2009

Если бы я был тобой, я бы сохранил значения этих глобальных переменных в файле когда файл dll освобождается и загружал их при инициализации. У меня так нет причин сохранять дамп памяти dll на диске.

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