Я бачив вихідний код Qt таким:
class Q_CORE_EXPORT QBasicAtomicInt
{
public:
...
};
Який Q_CORE_EXPORT
макрос визначає, як показано нижче:
define Q_DECL_IMPORT __declspec(dllimport)
То що __declspec(dllimport)
насправді означає?
Я бачив вихідний код Qt таким:
class Q_CORE_EXPORT QBasicAtomicInt
{
public:
...
};
Який Q_CORE_EXPORT
макрос визначає, як показано нижче:
define Q_DECL_IMPORT __declspec(dllimport)
То що __declspec(dllimport)
насправді означає?
Відповіді:
__declspec
є специфічним атрибутом Microsoft, який дозволяє вказати інформацію про клас зберігання.
(Nitpicker's Corner: Однак низка інших постачальників компіляторів - наприклад, GCC - тепер підтримує це мовне розширення для сумісності з встановленою базою коду, написаного для компіляторів Microsoft. Деякі навіть надають додаткові атрибути класу сховища.)
Двома з тих атрибутів класу сховища, які можна вказати, є dllimport
та dllexport
. Вони вказують компілятору, що функція або об'єкт імпортується або експортується (відповідно) з DLL.
Більш конкретно, вони визначають інтерфейс DLL для клієнта, не вимагаючи визначення модуля (.DEF
файлу ). Більшості людей набагато простіше використовувати ці розширення мови, ніж створювати файли DEF.
Зі зрозумілих причин __declspec(dllimport)
і, __declspec(dllexport)
як правило, поєднуються між собою. Ви використовуєте dllexport
для позначення символу як експортованого з DLL, і використовуєтеdllimport
для експортування цього експортованого символу в інший файл.
Через це, і оскільки один і той же заголовочний файл зазвичай використовується як під час компіляції DLL, так і в клієнтському коді, який використовує інтерфейс DLL, загальним шаблоном є визначення макросу, який автоматично перетворюється на відповідний специфікатор атрибутів під час компіляції. Наприклад:
#if COMPILING_DLL
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
А потім позначення всіх символів, які слід експортувати DLLEXPORT
.
Імовірно, саме це робить Q_CORE_EXPORT
макрос, вирішуючи або Q_DECL_IMPORT
або Q_DECL_EXPORT
.
__declspec
позначення як розширення мови С ++. Я вважаю, що GCC зараз це підтримує, але це в першу чергу з міркувань сумісності з компіляторами Microsoft. І я не розумію, чим "MS-specific" відрізняється від "specific-compiler". Корпорація Майкрософт написала компілятор C ++, і багато людей використовують її. Він поставляється з Visual Studio.
__declspec(dllimport)
це специфікатор класу сховища, який повідомляє компілятору, що функція або об'єкт або тип даних визначені у зовнішній бібліотеці DLL.
Функція або об'єкт або тип даних експортуються з DLL із відповідним __declspec(dllexport)
.
__declspec(dllexport)
повідомляє компілятору повідомити лінкера про те, що ці символи потрібно розмістити в таблиці експорту (при компілюванні .dll). Під час компіляції програми, яка зв'язується з .dll, __declspec(dllimport)
повідомляє компілятору, щоб він створив абсолютний абсолютний регістр-непрямий непрямий виклик (який компонувальник заповнить з роздільною здатністю, щоб вказати на таблицю імпорту), а не звичайний ріп-відносний регістр-прямийінструкція непрямого виклику до невизначеної функції (яка, оскільки не може змінити інструкцію, компоновщик вставляє відносну адресу транка, а потім створює транк, всередині якого розміщує відносний абсолютний регістр-непрямий непрямий виклик до покажчик функції в таблиці імпорту). Це оптимізація розміру та швидкості коду. Саме бібліотека імпорту .lib повідомляє компоновщику, які символи будуть імпортовані, і використовується як керівництво для створення таблиці імпорту та створення необхідних хитрощів у сегменті .text.
https://docs.microsoft.com/en-us/cpp/build/importing-function-calls-using-declspec-dllimport?view=vs-2019 https://docs.microsoft.com/en-us/cpp / build / importing-data-using-declspec-dllimport? view = vs-2019 https://stackoverflow.com/a/4490536/7194773
Це означає, що визначення функції знаходиться в динамічній бібліотеці. Докладнішу інформацію та приклади можна отримати в документації .