Я из мира Delphi, где статически импортировать функцию DLL довольно просто. Все, что вам нужно сделать, это указать имя функции и модуль следующим образом:
function GetTickCount : DWORD; stdcall; external 'Kernel32.dll';
Почему в C ++ я должен использовать kernel32.lib
для того, чтобы импортировать функцию? Почему я не могу просто сказать компоновщику импортировать эту функцию, как в Delphi?
Я знаю, что это может показаться нудистским для вас, но приход в мир C ++ из Delphi может действительно запутать.
Набор инструментов C ++ делает пару шагов, чтобы сделать то, что Delphi может сделать за один шаг. При объявлении внешней функции DLL в C ++ не существует (стандартного) способа указать, в какой именованной библиотеке DLL эта функция действительно может быть найдена. Что касается компилятора, объявленная функция просто extern
и должно быть определение, которое может быть найдено где-то компоновщиком.
Чтобы подключить именованную функцию к DLL, в которой она может быть найдена, для цепочки инструментов C ++ требуется «библиотека импорта», которая содержит заглушки импорта, с которыми компоновщик знает, что делать. При поиске функции, определенной в заглушке импорта, компоновщик создает ссылку на функцию DLL для конкретного имени функции в соответствующей библиотеке DLL (как указано в заглушке импорта).
В Delphi разработчики языка позволяли программисту указывать связанную DLL непосредственно в исходном коде. Затем компилятор Delphi может напрямую генерировать ссылку на внешнюю DLL без использования шага импорта-заглушки.
Ваш вопрос на самом деле является только проблемой компилятора Microsoft C ++ (MSVC), который требует использования «библиотеки импорта» в качестве промежуточного шага для привязки символов (то есть имен функций) к порядковым номерам функций в DLL. Это не проблема C ++ как таковая. Возможно, это еще одна раздражающая особенность компилятора MSVC, но я не знаю достаточно о мотивации такой схемы, чтобы комментировать, должна ли она быть или может быть изменена или нет. Если я правильно помню, компилятор C ++ Builder также работает с этим механизмом, имитирующим MSVC.
Большинство других компиляторов настраиваются на работу GCC (GNU Compiler Collection) с точки зрения связывания и двоичных интерфейсов. И те, которые не требуют этой дополнительной «библиотеки импорта», вы просто указываете соответствующую DLL в качестве части библиотек для связи с вашим исполняемым файлом.
Кстати, когда речь идет о различиях между компоновщиками C ++ и компоновщиком Delphi, эта проблема, которую вы указали, является лишь верхушкой айсберга. Они очень сильно отличаются друг от друга. Стандарт C ++ в значительной степени требует, чтобы компоновщик был достаточно простым (из-за «отдельной модели компиляции»), просто соединяя точки, так сказать, в то время как в Delphi компоновщик гораздо более тесно связан с компилятором и, как правило, умнее (и Быстрее).
Я только что отправил следующий запрос в QC: