Зачем нам нужен заглушка.lib, когда мы получили реальную реализацию.dll?

Мне интересно, почему компоновщики не могут выполнять свою работу, просто посмотрев информацию в реальных файлах.dll, которые получили фактический код реализации? я имею в виду, почему линкерам по-прежнему нужны файлы.lib для неявных линковок?

Разве таблицы экспорта и относительной адресации не достаточно для такой связи?

Есть ли способ, с помощью которого можно сделать неявное связывание, используя только.dll без файлов.lib stub/proxy?

я думал, что загрузчик исполняемых файлов Windows просто будет выполнять вызовы LoadLibrary/LoadLibraryEx от имени программы (отсюда и неявное связывание имени), что является основным отличием от явного связывания. если это так, то если делать это явно без.lib, это должно указывать на то, что это возможно без неявного, верно? или я просто говорю бессмысленно?

любая помощь приветствуется, большое спасибо:)

Geeko

1 ответ

Решение

Я могу придумать несколько причин.

  • Использование файлов.lib означает, что вы можете собрать версию DLL, отличную от той, которая установлена ​​в вашей системе, при условии, что у вас установлен правильный SDK.
  • Компиляторы и компоновщики должны поддерживать кросс-платформенные компиляции. Возможно, вы создаете 64-битную цель на 32-битной платформе и наоборот и не имеете правильной библиотеки DLL архитектуры.
  • Файлы.lib позволяют вам "скрывать" определенные части вашей реализации - у вас может быть частный экспорт, который не отображается в.lib, но обнаруживается через GetProcAddress. Вы также можете выполнить порядковый экспорт, и в этом случае они не экспортируют понятное имя, но могут иметь понятное имя в.lib.
  • Нативные библиотеки DLL не имеют строгих имен, поэтому может оказаться возможным подобрать неправильную версию библиотеки DLL.
  • И самое главное, эта технология была разработана в 1980-х годах. Если бы он был разработан сегодня, он, вероятно, был бы ближе к тому, что вы описываете - например, .NET, вам просто нужно сослаться на целевую сборку, и у вас есть все, что вам нужно для ее использования.

Я не знаю ни одного способа сделать неявное связывание исключительно с DLL - быстрый поиск выявил несколько инструментов, но я не использовал ни одного из них.

В этом случае я бы создал отдельный исходный файл с функциями, которые вам нужно использовать, и динамически загружал DLL и связывал их по мере необходимости. Например:

// using global variables and no-error handling for brevity.

HINSTANCE theDll = NULL;
typedef void (__stdcall * FooPtr)();
FooPtr pfnFoo = NULL;
INIT_ONCE initOnce;

BOOL CALLBACK BindDLL(PINIT_ONCE initOnce, PVOID parameter, PVOID context)
{
    theDll = LoadLibrary();
    pfnfoo = GetProcAddress(dll, "Foo");

    return TRUE;
}

// Export for foo
void Foo()
{
    // Use one-time init for thread-safe lazy initialization
    InitOnceExecuteOnce(initOnce, BinDll, NULL, NULL)
    pfnFoo();
}
Другие вопросы по тегам