В main.cpp в PluginLoader.exe в:Использование .DEF в Visual Studio вместо DllImport/dllexport с глобальными переменными
int Lives = 9;
Проект также содержит DEF-файл, который экспортирует переменную Lives (искаженное C++):
EXPORTS
[email protected]@3HA
Использование зависимостей ходунка, я проверил при открытии PluginLoader.exe что [email protected]@3HA
действительно экспортируется. Также экспортируется файл .lib, который должен содержать заглушки, с которыми мы можем ссылаться в других проектах. Использование dumpbin.exe на поворотном PluginLoader.lib я получаю:
4 [email protected]@3HA
1 __IMPORT_DESCRIPTOR_PluginLoader
2 __NULL_IMPORT_DESCRIPTOR
4 [email protected]@3HA
3 ⌂PluginLoader_NULL_THUNK_DATA
PluginLoader загружается в SimplePlugin.dll с помощью LoadLibrary/GetProcAddress. SimplePlugin.dll имеет main.cpp, который выглядит следующим образом:
extern int Lives;
extern "C" __declspec(dllexport) void PluginMain()
{
++Lives;
}
SimplePlugin также связывает против заглушки PluginLoader.lib. При попытке увеличить Lives я всегда сбой с НАРУШЕНИЕМ ДОСТУПА. Похоже, что мой SimplePlugin.dll псевдовырабатывает свою версию переменной Lives, даже если она связана с заглушкой.
Если я изменяю только живет SimplePlugin к:
__declspec(dllimport) extern int Lives;
Все работает, как ожидалось. Почему это? Я думал, что целью .def было не использовать dllexport/dllimport. Моя текущая гипотеза заключается в том, что dllimport с глобальной переменной делает некоторые хитрости за кулисами (как работает &Lives
в dll и exe?). Связано ли это с [email protected]@3HA
?
Примечание: Импорт указателей функций без dllimport работает отлично. Его единственное с глобальными переменными, что я получаю крах. Это воспроизводит в VS 2010 и 2012
Образец проекта: https://db.tt/maV0oWop
глобальная переменная не может быть безопасно экспортируется, только указатель на такую переменную. Требуется, чтобы DLL могла быть перемещена. Используя __declspec, вы сообщите компилятору о том, чтобы позаботиться об этом указателе для вас, не делая ничего другого. Рекомендуется, конечно. Также рекомендуется использовать функции доступа (Get/SetLives). –