在Linux程序中,.dll文件是做什么用的?

使用Unity3D制作的Linux游戏在其数据文件夹中包含.dll文件。

这很奇怪,因为我以为Linux使用.so文件而不是.dll文件。

(对于Android-Unity3D应用程序也是如此。)

为什么呢?

2个回答

你所提到的游戏是基于.NET Framework并使用Mono运行,Mono是Microsoft .NET Framework的免费开源实现。

由于这些应用程序是基于.NET的,因此程序集具有.dll扩展名。所以你可以在文件夹中看到DLL文件。

为了实现跨平台,一个设计用于多平台的.NET程序可以在Windows、Linux或Mac上运行,使用相同的"二进制文件"(包括也是程序集的DLL文件),这些文件编译为MSIL,并需要.NET/Mono运行时来执行。

请注意,在Ubuntu软件仓库中还有一些基于Mono Framework的免费应用程序(不仅限于游戏)。例如:Tomboy。


11请注意,那些dll不是“真正的”Windows dll,而实际上是编译的.NET字节码。 - Sanya_Zol
5请注意,在Linux中,文件扩展名,包括.dll.so,是没有意义的。它们只是为了我们的方便而使用的。 - code_dredd
1@ray 你能解释一下吗?我以为它们仍然是传递文件类型信息的标准,所以并不是毫无意义的吗? - FMaz
2@FynnMazurkiewicz:这更多是略有不同的设计传统问题,而不是一个单一的中心属性,_任何一个_系统都可以实现。事实上,_Windows核心_和Linux动态链接器都会愉快地加载共享库(各自的格式),无论其_文件名_是否以.dll或.so结尾,甚至其他后缀也可以。出于历史原因,如果在Windows中的LoadLibrary系统调用的文件名没有扩展名,它有时会追加".dll",但这通常不是_常见的用法_。 - hmakholm left over Monica
1@ray 不完全正确:如果库文件的文件名不以.so.a或其版本化变体结尾,gcc将无法找到像-lm这样提供的库。 - Ruslan
1@Ruslan,gcc-l选项的man页面表明你指出的只是一种惯例,而不是扩展名实际上是必需的。 "链接器会在标准目录列表中搜索库文件,实际上是一个名为liblibrary.a的文件... [the] -l会在library两侧加上lib和.a,并搜索多个目录。" - code_dredd
@FynnMazurkiewicz 对于操作系统来说,它们是没有意义的。对我们来说,它们确实传达了一些视觉信息,因为我们不会期望通过文件元数据中的魔术字节来确定它是真正的文本文件还是可执行文件。考虑一下内置命令(例如lscat等),它们都没有文件扩展名来“标记”它们为可执行文件;实际上,它们能够执行是由文件权限和它们是程序这个事实共同决定的。如果一个可执行文件被重命名为.txt扩展名,并且具有正确的权限设置,仍然可以运行它。 - code_dredd
如果根据对其他Windows程序的经验来说,我们可以简单地在没有扩展名的DLL文件后面添加一个.,这样它就可以在加载时不会自动添加.dll - wizzwizz4
@wizzwizz4:没错。这也有文档记录 - hmakholm left over Monica

GameDataFolder/Managed中的.dll文件属于一个内部使用Mono的本机代码程序。

Unity游戏引擎嵌入Mono(即使在大多数Windows平台上也是如此)。

跨平台的可执行文件和共享库,既可以由.NET公共语言运行时,也可以由Mono运行,通常分别使用.exe.dll后缀进行命名,即使它们不仅限于Windows。当您在像Ubuntu这样的GNU/Linux系统的程序中找到一个.dll文件,或者对于除Windows以外的任何操作系统,通常就是这个原因。通常情况下,您在Ubuntu系统中找到.dll文件时,Golboth's answer解释了其中的原因。但这里发生的事情稍有不同。

Unity游戏引擎--不要与大多数Ubuntu版本中的默认图形界面混淆--是一款流行的专有跨平台游戏引擎。 该引擎在.NET Framework或Mono之上运行。 相反,它嵌入了Mono, 也就是说Mono在其之上运行。这是开发人员编写游戏所需代码的方式,这些代码不是Unity引擎的一部分。

一般来说,Mono可以像微软的.NET CLR一样使用,用于运行完整的.NET/Mono程序。但是Mono还被设计成可以轻松嵌入到本地代码应用程序中,包括使这些应用程序能够进行定制。这就是你所描述的情况。你看到的文件不属于直接在Mono或.NET CLR之上运行的程序,而是属于嵌入了Mono的本地代码程序。
Unity游戏引擎如何使用Mono
Unity游戏引擎主要使用C++编写,它自带了一个Mono实例,与通过系统软件包管理器安装的版本(如果有的话)可能不同。这个嵌入式的Mono运行时不能用来运行独立的.NET/Mono程序,因为这不是它的目的。相反,引擎的本地代码部分使用它来运行CIL代码。(CIL是Common Intermediate Language,这是它的官方名称。它以前被称为MSIL或Microsoft Intermediate Language,因为最初是由微软开发的。)使用Unity引擎制作游戏的程序员通常会使用C#编写自己的代码,尽管也支持其他一些语言。
Unity引擎即使在Windows中也嵌入了Mono。对于通用Windows平台游戏,它使用Microsoft .NET Framework而不是Mono。但是大多数Unity游戏在大多数平台上,包括大多数移动设备和游戏机,以及Ubuntu和Windows,都使用Mono。在某些平台上,IL2CPP可作为Mono的替代方案,而在少数平台上只支持IL2CPP。有关详细信息,请参阅脚本限制

在Ubuntu上可能会看到.dll文件的其他情况

已经描述了两种在Ubuntu上可能会看到.dll文件的情况:

一个共享库,旨在供.NET/Mono应用程序使用。Golboth's answer详细描述了这一点。这就是你在Ubuntu系统上看到的大多数.dll文件。只是恰好不是你的GameDataFolder/Managed文件夹中的.dll文件的用途。
一个提供代码的文件,由嵌入式Mono运行时用于为本地代码应用程序提供“脚本”。这就是这种情况下正在发生的事情。
还有两种常见情况下,你可能会在Ubuntu上看到.dll文件:
  1. .NET Core的编译器生成的是.dll文件,而不是.exe文件,即使你要编译的内容并非库。这些文件在.NET Core运行时(称为CoreCLR)上运行,而不是普通的.NET Framework或Mono。.NET Core是微软的产品,但与标准的.NET Framework不同,.NET Core是跨平台的,对GNU/Linux系统(如Ubuntu)有官方支持,并且它是免费开源软件
  2. 有时,在Ubuntu上看到的.dll文件只是一个Windows库。如果程序存储在Ubuntu系统上但在Windows上运行,或者在Ubuntu中挂载了Windows驱动器,您可能会看到这种情况。您还可能在与能够使用Wine在Ubuntu上运行的程序相关联的情况下看到它,包括使用Wine提供的软件或使用winetricks自动安装以支持其他Windows软件的软件。
这并不是要详尽列举在Ubuntu上可能遇到.dll的所有情况。(例如,它也可能是一个OS/2库。)然而,我相信这四种情况是最常见的。