gpt4 book ai didi

c# - 如何在单声道中设置 dllimport 的搜索路径?

转载 作者:太空宇宙 更新时间:2023-11-03 12:28:30 25 4
gpt4 key购买 nike

我正在开发一个 Unity 应用程序,它需要从安装应用程序的外部动态加载 native 库,由于某种原因,我无法将绝对路径设置为 DllImport在编译之前(例如在运行时读取 .txt 中的库路径并加载它),并且我不想使用特定于平台的 API,例如 LoadLibrary()在 Windows 上或 dlopen在 Linux 上,因为它不方便。而我已经挣扎了好几天。

我知道搜索路径可以通过SetDllDirectory()调整在 Windows 上来自 this post ,并且在 .NET Framework 应用程序上进行测试时效果很好。
但是,它在基于 mono 2.0 的 Unity 中不起作用,它只会抛出 DllNotFoundException在运行时,但是当我在 DllImport 中使用绝对路径时它工作正常或者将dll复制到我的Unity项目中(我确定代码是一样的)

我尝试的下一个方法是环境变量,它不适用于 .NET 和 Mono,this post解释了 CLR 在流程执行期间从不刷新环境。

我尝试的第三种方法是使用特定于平台的 API 加载 native 库,例如 LoadLibrary()在 Windows 和 dlopen() 上首先在 Linux 上,然后是 Dllimport可能会发现同名的库已经被加载了,那么它会使用加载库来查找函数指针,就像this post做过。我得到了同样的结果。该问题的最佳答案是我们可以编写一个包装类,它使用特定于平台的 API 来显式加载库并获取函数指针,而不是专注于 Dllimport 的方法。 ,但这不是我想要的。

如果我的猜测是正确的,根据 mono's document , DllImportAttribute来电LoadLibrarydlopen在运行时内部将库加载到内存空间中。所以它遵循特定操作系统平台的搜索规则,例如windows:

  • 加载应用程序的目录。
  • 当前目录
  • 系统目录。使用 GetSystemDirectory()函数获取该目录的路径。
  • 16 位系统目录。
  • Windows 目录。使用 GetWindowsDirectory()获取函数
    此目录的路径。
  • PATH 环境变量中列出的目录。

  • 和 Linux:
  • 用户的 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进程启动时只解析一次,类似于 PATH Windows 上的环境变量。

    所以我的问题是:
  • 为什么相同的代码在 .NET Framework 和 Mono 上执行不同? Mono 是否忽略了 SetDllDirectory() 的影响?在 Windows 上? DllImportAttribute 是什么意思真的在 Mono 中做吗?
  • 有什么方法可以在运行时调整 Unity/Mono 应用程序的搜索路径,只需使用 DllImport而不是平台特定的 API,例如 LoadLibrary()dlopen() ?
  • 最佳答案

    不幸的是,答案是这种行为在 Linux 上的 Mono 和 Windows 上的 .Net 之间是不同的,所以你只需要处理这个问题。

    如果您知道每个 DLL 的位置(例如,您可以将其放入配置文件),最好的选择是使用 LoadLibrary 自己显式加载每个 DLL。或 dlopen .这必须在第一次调用 DllImport 之前完成。功能。 DllImport那么不需要指定路径。

    这样您就可以准确地知道您正在获取哪个 DLL,并且可以以任何正确的顺序加载它们(如果这是一个问题)。

    如果出于某种原因你真的不想这样做,我建议你创建一个类似 MySetDllDirectory 的函数。在 Windows 上调用 SetDllDirectory在 Linux 上设置 LD_LIBRARY_PATH .通过这种方式,可以将更改隔离到单个模块。

    关于c# - 如何在单声道中设置 dllimport 的搜索路径?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43679863/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com