我正在开发一个 Unity 应用程序,需要动态从安装位置之外加载本地库。由于某种原因,我不能在编译前设置
我知道可以通过 Windows 上的
我尝试的下一步方法是使用环境变量,在 .NET 和 Mono 上都不起作用,此帖子 解释说 CLR 在进程执行期间从不刷新环境。
我尝试的第三种方法是首先使用特定于平台的 API(例如在 Windows 上使用
如果我的猜测正确,则根据 mono 文档 ,
DllImport
的绝对路径(如在运行时读取库路径的 .txt),也不想使用特定于平台的 API,例如 Windows 上的 LoadLibrary()
或 Linux 上的 dlopen
,因为这样很麻烦。我已经为此奋斗了几天。我知道可以通过 Windows 上的
SetDllDirectory()
调整搜索路径,来自 此帖子,当在 .NET Framework 应用程序上进行测试时,它运行良好。
但是在基于 mono 2.0 的 Unity 中却不起作用,它只会在运行时抛出 DllNotFoundException
,但是当我在 DllImport
中使用绝对路径或将 dll 复制到我的 Unity 项目中时(我确定代码相同),它能够正常工作。我尝试的下一步方法是使用环境变量,在 .NET 和 Mono 上都不起作用,此帖子 解释说 CLR 在进程执行期间从不刷新环境。
我尝试的第三种方法是首先使用特定于平台的 API(例如在 Windows 上使用
LoadLibrary()
或在 Linux 上使用 dlopen()
)加载本地库,然后 Dllimport
可能会发现同名库已经被加载,然后它将使用加载库来查找函数指针,就像此帖子所述。我得到了相同的结果。该问题的最佳答案说我们可以编写一个包装器类,该类使用特定于平台的 API 显式地加载库并获取函数指针,而不是专注于 Dllimport
的方法,但这不是我想要的。如果我的猜测正确,则根据 mono 文档 ,
DllImportAttribute
在运行时内部调用 LoadLibrary
或 dlopen
来将库加载到内存空间中。因此,它遵循特定于操作系统平台的搜索规则,例如 Windows:
- 应用程序加载的目录。
- 当前目录
- 系统目录。使用
GetSystemDirectory()
函数获取此目录的路径。 - 16 位系统目录。
- Windows 目录。使用
GetWindowsDirectory()
函数获取此目录的路径。 - 列在 PATH 环境变量中的目录。
- 用户的
LD_LIBRARY_PATH
环境变量中用冒号分隔的目录列表。这是一种常用的方法,允许CLI程序找到本地共享库。 /etc/ld.so.cache
中缓存的库列表。/etc/ld.so.cache
是通过编辑/etc/ld.so.conf
并运行ldconfig(8)
创建的。编辑/etc/ld.so.conf
是搜索附加目录的首选方式,而不是使用LD_LIBRARY_PATH
,因为这更安全(将木马库插入/etc/ld.so.cache
比将其插入LD_LIBRARY_PATH
更困难)。/lib
,然后是/usr/lib
。
顺便说一下,我也尝试在运行时设置LD_LIBRARY_PATH
,但它不起作用,因为LD_LIBRARY_PATH
只会在进程启动时解析一次,这类似于Windows上的PATH
环境变量。
所以我的问题是:
- 为什么相同的代码在.NET Framework和Mono上表现不同?Mono是否在Windows上忽略了
SetDllDirectory()
的效果?DllImportAttribute
在Mono中实际上是做什么的? - 是否有任何方法可以在运行时调整Unity/Mono应用程序的搜索路径,只使用
DllImport
而不是平台特定的API,如LoadLibrary()
和dlopen()
?