Наличие нескольких экземпляров глобальных переменных из одной и той же DLL - PullRequest
1 голос
/ 29 марта 2011

В настоящее время у меня есть система со следующим упрощенным представлением.

The entire system run under single process
------------------------------------------
       --- DLL0.DLL --- COMMON.DLL (contains global_variable in COMMON.DLL)
EXE ---|
       --- DLL1.DLL --- COMMON.DLL (contains global_variable in COMMON.DLL)

Исходный код COMMON.DLL выглядит следующим образом.

// COMMON.DLL
#ifdef COMMON_EXPORTS
_declspec( dllexport ) int global_variable = 100;
// Function used to access and print global_variable.
__declspec(dllexport) void common_fun_which_access_global_variable();
#else
_declspec(dllimport) int global_variable;
__declspec(dllimport) void common_fun_which_access_global_variable();
#endif

Исходный коддля DLL0.DLL выглядит следующим образом.

__declspec(dllexport)
void DLL0() {
    printf ("This is DLL0\n");
    printf ("In DLL0, global_variable is %i\n", global_variable);
    common_fun_which_access_global_variable();
    global_variable = 200;
    printf ("DLL0 is now setting global_variable to 200\n");
    common_fun_which_access_global_variable();
}

Исходный код для DLL1.DLL выглядит следующим образом.

__declspec(dllexport)
void DLL1() {
    printf ("This is DLL1\n");
    printf ("In DLL1, global_variable is %i\n", global_variable);
    common_fun_which_access_global_variable();
    global_variable = 400;
    printf ("DLL1 is now setting global_variable to 400\n");
    common_fun_which_access_global_variable();
}

Исходный код для EXE выглядит следующим образом.

HINSTANCE instance0 = AfxLoadLibrary(_T("DLL0.dll"));
FARPROC fun0 = GetProcAddress(instance0, "DLL0");
HINSTANCE instance1 = AfxLoadLibrary(_T("DLL1.dll"));
FARPROC fun1 = GetProcAddress(instance1, "DLL1");
_fun0();
_fun1();

Вывод выглядит следующим образом.

This is DLL0
In DLL0, global_variable is 100
In COMMON, global_varialbe is 100
DLL0 is now setting global_variable to 200
In COMMON, global_varialbe is 200

This is DLL1
In DLL1, global_variable is 200    <-- I wish 100 is being printed.
In COMMON, global_varialbe is 200  <-- I wish 100 is being printed here too.
                                   <-- I wish DLL0 and DLL1 have their own instance of
                                   <-- global_variable respectively.
DLL1 is now setting global_variable to 400
In COMMON, global_varialbe is 400

Вся система выполняется в рамках одного процесса.Хотя DLL0.DLL и DLL1.DLL загружаются явно каждая, зависимость COMMON.DLL будет загружаться только один раз за весь жизненный цикл приложения.EXE не будет загружать один и тот же COMMON.DLL дважды.

Есть ли способ, которым я могу добиться следующего без нарушения одного из правил?

  1. DLL0 и DLL1 могут иметь свой собственный экземпляриз global_variable?
  2. global_variable должен быть глобальным, а внутреннее COMMON.DLL?
  3. COMMON.DLL будет загружено через неявное связывание с использованием файла LIB.
  4. Нет переименования COMMON.DLL в COMMON-DLL0.DLL и COMMON-DLL1.DLL.
  5. Нет статического связывания.
  6. Если DLL0 изменит значение global_variable, вызов common_fun_which_access_global_variable из DLL0 должен получить доступ кDLL0 изменило значение.Тем не менее, вызов common_fun_which_access_global_variable из DLL1 не должен реализовывать изменения.

** Я знаю, что это слишком много.Но сейчас я имею дело с устаревшим кодом.Вы знаете:)

Сможет ли параллельная сборка решить эту проблему?Я понимаю, что параллельная сборка используется для решения нескольких DLL с одинаковыми именами, но с разными версиями.Я не уверен, применимо ли это в моем случае выше?

Или я должен спросить об обратном?Как мы можем загрузить 2 экземпляра COMMON.DLL в один и тот же EXE-файл?

Ответы [ 3 ]

2 голосов
/ 29 марта 2011

Если я правильно понимаю ситуацию, COMMON.dll является устаревшим кодом, а устаревший код используется как DLL0.dll, так и DLL1.dll.

Не зная всех деталей, я бы предложил следующее:

1) Создайте глобальную переменную в DLL0.dll и DLL1.dll.
2) Инициализируйте каждую глобальную переменную из шага 1 с помощью значения global_variable COMMON.dll.
3) При необходимости используйте две новые глобальные переменные.

1 голос
/ 21 декабря 2011

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

Можно ли переписать ваши DLL0 и DLL1 для взаимодействия с файлом COMMON.dll через оболочку? Если это так, вызовите обертку отдельным процессом для взаимодействия с common.dll. Затем оболочка использует некоторую форму IPC (возможно, совместно используемую память) для связи с рабочим процессом.

Конечно, это гораздо сложнее, чем просто копировать файл common.dll под новым именем ... Вы уверены, что это стоит того?

0 голосов
/ 27 сентября 2016

У меня была именно эта проблема, когда я не мог контролировать сторонние DLL0, DLL1 или COMMON.

Решением, которое я создал, было дублирование COMMON с разными именами и исправление DLL0 и DLL1 для загрузки ихсобственные копии.

(в моем случае мне пришлось запустить много копий уровня 'DLL0', поэтому я написал программу, которая дублировала 'DLL0' и 'COMMON' для каждого нужного мне экземпляра, а затем исправил«DLL0» копирует новое имя COMMON. Новые имена должны были иметь ту же длину, что и оригинал, и из памяти это был просто поиск и замена конкретного текста имени, хотя из памяти существовали разновидности ANSI и WIDE.Конечно, этот подход может больше не работать, если DLL подписаны?)

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