.dll 或 .so 是共享库(在运行时链接),而 .a 和 .lib 是静态库(在编译时链接)。这在 Windows 和 Linux 之间没有区别。
不同之处在于,它们是如何处理的。注意:区别仅在于海关,它们是如何使用的。以 Windows 的方式构建 Linux 并不太难,反之亦然,但实际上没有人这样做。
如果我们使用 dll,或者我们甚至从我们自己的二进制文件中调用一个函数,有一个简单明了的方法。例如,在 C 中,我们看到:
int example(int x) {
...do_something...
}
int ret = example(42);
但是,在 asm 级别上,可能存在许多差异。例如,在 x86 上,执行 call 操作码,并在堆栈上给出 42。或在某些寄存器中。或任何地方。没有人知道在编写 dll 之前,它将如何使用它。或者项目将如何使用它,可能是用现在甚至不存在的编译器(或用一种语言!)编写的(或者对于 dll 的开发人员来说是未知的)。
例如,默认情况下,C 和 Pascal 都从堆栈中放入参数(并获取返回值) - 但它们的执行顺序不同。您还可以通过一些依赖于编译器的优化在寄存器中的函数之间交换参数。
如你所见,Windows 的习惯是构建一个 dll,我们还用它创建了一个最小的.a/.lib。这个最小的静态库只是一个包装器,通过它可以访问该 dll 的符号(函数)。这会进行所需的 asm 级调用转换。
它的优点是兼容性。它的缺点是,如果你只有一个 .dll,你可能很难弄清楚它的函数是如何被调用的。这使得 dll 的使用成为一项黑客任务,如果 dll 的开发者没有给你.a。因此,它主要服务于封闭性目的,例如更容易为 SDK 获得额外的现金。
它的另一个缺点是即使使用动态库,也需要静态编译这个小包装器。
在 Linux 中,dll 的二进制接口是标准的并且遵循 C 约定。因此,不需要.a,并且共享库之间存在二进制兼容性,作为交换,我们没有微软自定义的优势。