2015-07-08 2 views
1

В 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

+0

глобальная переменная не может быть безопасно экспортируется, только указатель на такую ​​переменную. Требуется, чтобы DLL могла быть перемещена. Используя __declspec, вы сообщите компилятору о том, чтобы позаботиться об этом указателе для вас, не делая ничего другого. Рекомендуется, конечно. Также рекомендуется использовать функции доступа (Get/SetLives). –

ответ

1

компилятор действительно генерирует код разыменования при использовании dllimport данных.

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

MS docs on that

Смежные вопросы