я в процессе написания набор библиотек, где выступает в качестве основного компонента , позднее связывание других через плагин API. Теперь проблема заключается в следующем:Используя макрос, который получает доступ к глобальной переменной внутри плагин
В основной библиотеке содержится класс ведения журнала, а также набор макросов для облегченного ведения журнала.
/* File: Log.h */
namespace XYZ
{
class XYZ_API Log
{
/* Logfile and console output management */
};
// Global log object
extern XYZ_API Log logger;
// Macros using aforementioned variable
#ifndef XYZ_DISABLE_LOGGING
#define LOG_DEBUG(msg) /* statements using logger object */
#define LOG_INFO(msg) /* etc. */
#else
#define LOG_DEBUG(msg)
#define LOG_INFO(msg)
#endif
}
Определения переменного регистратора так просто, как он получает:
/* File: Log.cpp */
namespace XYZ
{
// Initialize the global log object
Log logger;
/* Log class implementation */
}
Теперь, когда делает использование этих макросов из самих или от клиентского приложения основной библиотеки, все работает просто хорошо. Но как только я пытаюсь использовать их в одном из плагинов:
/* File: MyPlugin.cpp */
namespace XYZ
{
MyPlugin::MyPlugin(/* ... */)
{
LOG_INFO("This won't link!");
logger.
}
}
Следующая ошибка линкера возникает (с использованием набора инструментов V110 MSVC):
LNK2001: unresolved external symbol "class XYZ::Log XYZ::logger" ([email protected]@@[email protected]@A)
Это, как говорится, это самый символ, безусловно, является экспортируется из библиотеки плагинов (присутствует в файле .lib). Плагин также связан с основной библиотекой. Другие символы (классы и их методы) отлично работают.
Я понимаю, что для загрузки во время загрузки символов из загруженной DLL необходимо запросить GetProcAddress/dlsym (или какой-либо эквивалент). Кроме того, у меня есть интерфейс, который может через чисто виртуальный класс сделать любой объект из основной библиотеки, доступной для плагинов.
Сейчас для Актуальный вопрос: Есть ли способ сделать вышеуказанный план работы, или я должен воздерживаться от использования макросов регистрации в коде плагина?
Edit:
опций командной строке компилятора (библиотека ядра) являются (длинные имена путей раздели):
/GS /analyze- /W3 /Zc:wchar_t /I"[...]" /ZI /Gm /Od /Fd"[...]" /fp:precise /D "XYZ_EXPORT_SYMBOLS" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /Oy- /MDd /Fa"[...]" /EHsc /nologo /Fo"[...]" /Fp"[...]"
И для компоновщика:
/OUT:"[...]" /MANIFEST /NXCOMPAT /PDB:"[...]" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /IMPLIB:"[...]" /DEBUG /DLL /MACHINE:X86 /INCREMENTAL /PGD:"[...]" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"[...]" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1
Same вещь для библиотеки плагинов; в значительной степени точно такая же строка, за исключением путей:
/GS /analyze- /W3 /Zc:wchar_t /I"[...]" /ZI /Gm /Od /Fd"[...]" /fp:precise /D "XYZ_EXPORT_SYMBOLS" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /Oy- /MDd /Fa"[...]" /EHsc /nologo /Fo"[...]" /Fp"[...]"
И подключение плагинов; Опять же, в основном та же линия, за исключением ссылки на основную библиотеку:
/OUT:"[...]" /MANIFEST /NXCOMPAT /PDB:"[...]" /DYNAMICBASE "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" "[path to core lib]" /IMPLIB:"[...]" /DEBUG /DLL /MACHINE:X86 /INCREMENTAL /PGD:"[...]" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"[...]" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1
Спасибо за ваш ответ!Хорошо, я наткнулся на список Microsoft относительно причин LNK2001 ранее, но не смог связать какие-либо проблемы, перечисленные там, в моей ситуации. Тем не менее, я добавил свои параметры командной строки выше, надеюсь, что это поможет! – Zultar
Я использовал эти проблемы при некорректном упорядочении библиотеки из памяти. Я не вижу, где вы ошибаетесь. Вы пытались явно указать «/ EXPORT: logger» или «/ EXPORT: XYZ :: logger» в сборке ядра lib, а также попробовать '/ FORCE' в плагине lib, чтобы узнать, помогает ли она преодолеть ошибку связывания. –
Я такой толстый. Я случайно определил один и тот же макрос экспорта в обоих библиотечных компонентах. Из-за этого 'XYZ :: logger' был объявлен' dllexport' для плагина. Неудивительно, что это не сработало. В любом случае, спасибо, что указали мне в правильном направлении! :) – Zultar