当我们获得实际的 .dll 实现时,为什么我们仍然需要 .lib 存根文件?

发布于 2024-08-01 19:11:01 字数 333 浏览 9 评论 0原文

我想知道为什么链接器不能仅仅通过查阅获得实际实现代码的实际 .dll 文件中的信息来完成其工作? 我的意思是为什么链接器仍然需要 .lib 文件来进行隐式链接?

导出和相对地址表不足以进行此类链接吗?

无论如何,是否可以仅使用 .dll 而不使用 .lib 存根/代理文件进行隐式链接?

我认为 Windows 可执行加载程序只会代表程序执行 LoadLibrary/LoadLibraryEx 调用(因此称为隐式链接),这是与显式链接的主要区别。 如果这是真的,那么在没有 .lib 的情况下显式地执行该操作应该表明在没有 .lib 的情况下它也是可行的,对吗? 或者我只是说无意义?

i'm wondering why linkers can not do their job simply by consulting the information in the actual .dll files that got the actual implementation code ? i mean why linkers still need .lib files to do implicit linking ?

are not the export and relative address tables enough for such linking ?

is there anyway by which one can do implicit linking using only the .dll without the .lib stub/proxy files ?

i thought the windows executable loader would simply do LoadLibrary/LoadLibraryEx calls on behalf of the program (hence the name implicit linking) which is the main difference to explicit linking. if that is true then doing it explicitly without .lib should indicate that it is doable without it implicitly, right ? or i'm just saying non sense?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

埖埖迣鎅 2024-08-08 19:11:01

我可以想到几个原因。

  • 使用 .lib 文件意味着您可以构建与系统上不同版本的 DLL,前提是您安装了正确的 SDK。
  • 编译器和 链接器需要支持跨平台编译 - 您可能在 32 位平台上构建 64 位目标,反之亦然,但没有正确的体系结构 DLL。
  • .lib 文件使您能够“隐藏”实现的某些部分 - 您可以拥有不显示在 .lib 中但可通过 GetProcAddress 发现的私有导出。 您还可以进行序数导出,在这种情况下,它们不会导出友好名称,但会在 .lib 中具有友好名称。
  • 本机 DLL 没有强名称,因此可能会选择错误版本的 DLL。
  • 最重要的是,这项技术是在 20 世纪 80 年代设计的。 如果它是今天设计的,它可能会更接近您所描述的 - 例如,.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();
}

I can think of a a few reasons.

  • Using .lib files mean you can build for a different version of a DLL than you have on your system, provided you just have the correct SDK installed.
  • Compilers & linkers need to support cross-platform compilations - You might be building for a 64-bit target on a 32-bit platform and vice-versa and not have the correct architecture DLL present.
  • .lib files enable you to "hide" certain parts of your implementation - you could have private exports that do not show up in the .lib but are discoverable via GetProcAddress. You can also do ordinal exports in which case they don't have a friendly name exported, but would have a friendly name in the .lib.
  • Native DLL's do not have strong names, so it may be possible to pick up the wrong version of the DLL.
  • And most importantly, this technology was designed in the 1980's. If it were designed today, it'd probably be closer to what you describe - for instance, .NET you just need to reference the target assembly and you have everything you need to use it.

I don't know of any way to do implicit linking solely with the DLL - A quick search revealed several tools, but I haven't used any of them.

In this case, I would create a separate source file with the functions you need to use, and dynamically load the DLL and bind them as needed. For example:

// 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();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文