что на самом деле означает __declspec (dllimport)?

92

Я видел исходный код Qt вот так:

class Q_CORE_EXPORT QBasicAtomicInt
{
public:
...
};

Какой Q_CORE_EXPORTмакрос определяет, как показано ниже:

define Q_DECL_IMPORT __declspec(dllimport)

Так что же на __declspec(dllimport)самом деле значит?

гемфилд
источник
2
возможный дубликат Почему / когда __declspec (dllimport) не нужен?
Hans Passant

Ответы:

118

__declspec- это специфичный для Microsoft атрибут, позволяющий указать информацию о классе хранения.
(Уголок Nitpicker's: однако ряд других поставщиков компиляторов, например 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 не является должным образом «специфичным для MS» (он гораздо более специфичен для компилятора), и некоторые компиляторы также используют это объявление для нескольких платформ. Некоторые из значений атрибутов (dllexport / dllimports специфичны для MS, на самом деле, поскольку DLL - это MS lexicon)
Эмилио Гаравалья
9
@Emilio: Насколько мне известно, Microsoft изобрела __declspecнотацию как расширение языка C ++. Я считаю, что GCC теперь поддерживает его, но это в первую очередь из соображений совместимости с компиляторами Microsoft. И я не понимаю, чем "специфичный для MS" отличается от "специфичного для компилятора". Microsoft написала компилятор C ++, и многие люди его используют. Он поставляется с Visual Studio.
Коди Грей
8
Microsoft делает компилятор. Он называется «Оптимизирующий компилятор Microsoft C / C ++», cl.exe. Многие люди ошибочно называют Visual Studio компилятором, но это IDE. Я не знаю, почему люди придираются к тому, что означает «специфично для Microsoft». Это не означает «среду MS» (что бы это ни было), и уж точно не означает «Windows». Да, другие поставщики компиляторов теперь поддерживают расширение для совместимости с установленной базой кода, написанного для компиляторов Microsoft. Как я уже говорил, насколько мне известно, Microsoft изобрела синтаксис. Вот что здесь сказано.
Коди Грей
2
@CodyGray: Одного его изобретения недостаточно. Тем не менее, Microsoft изобрела его, нет стандарта, содержащего его, другие реализуют его только для совместимости, и он используется в основном (если не исключительно) для программ, нацеленных на Microsoft Windows, вместе делает очень сильным
аргументом
6
Это отличный ответ, особенно в части, «потому что один и тот же заголовочный файл обычно используется как при компиляции DLL, так и в клиентском коде»! Делает каждый аспект импорта / экспорта кристально понятным.
Ela782
30

__declspec(dllimport) - спецификатор класса хранения, который сообщает компилятору, что функция, объект или тип данных определены во внешней DLL.

Функция, объект или тип данных экспортируется из библиотеки DLL с соответствующим файлом __declspec(dllexport).

arx
источник
6
ОК. Наконец, после 2 часов чтения я нашел наиболее удовлетворительное, краткое и точное изложение того, что я хочу.
el psy Congroo
1

__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

Льюис Келси
источник
-2

Это означает, что определение функции находится в динамической библиотеке. Обратитесь к документации для получения более подробной информации и примеров.

Армен Цирунян
источник