【问题标题】:DllNotFoundException in unity3d plugin for c++ dllc++ dll的unity3d插件中的DllNotFoundException
【发布时间】:2012-04-03 23:40:38
【问题描述】:

我正在开发 Unity Plugin 项目并尝试从 c# 文件导入 c++ 本机 dll。 但我不断收到 dllnotfoundexception。

c++ dll 代码:

extern "C" {
extern __declspec( dllexport ) bool IGP_IsActivated();
}

c#代码:

[DllImport("mydll")]
    private static extern bool IGP_IsActivated();

Dll 已就位且 FIle.Exists 正常工作。所有依赖的 dll 都存在于相同的层次结构中,但我仍然以 dllnotfound 异常告终。

任何帮助,非常感谢!

【问题讨论】:

  • 插件在某处可用吗?

标签: unity3d


【解决方案1】:

感谢Unity forum post,我想出了一个很好的解决方案,它可以在运行时修改PATH-环境变量:

  • 所有 DLL(Unity 与之交互的DLL 及其依赖的DLL)放入Project\Assets\Wherever\Works\Best\Plugins
  • 将以下静态构造函数放入使用插件的类中:

    static MyClassWhichUsesPlugin() // static Constructor
    {
        var currentPath = Environment.GetEnvironmentVariable("PATH",
            EnvironmentVariableTarget.Process);
    #if UNITY_EDITOR_32
        var dllPath = Application.dataPath
            + Path.DirectorySeparatorChar + "SomePath"
            + Path.DirectorySeparatorChar + "Plugins"
            + Path.DirectorySeparatorChar + "x86";
    #elif UNITY_EDITOR_64
        var dllPath = Application.dataPath
            + Path.DirectorySeparatorChar + "SomePath"
            + Path.DirectorySeparatorChar + "Plugins"
            + Path.DirectorySeparatorChar + "x86_64";
    #else // Player
        var dllPath = Application.dataPath
            + Path.DirectorySeparatorChar + "Plugins";
    
    #endif
        if (currentPath != null && currentPath.Contains(dllPath) == false)
            Environment.SetEnvironmentVariable("PATH", currentPath + Path.PathSeparator
                + dllPath, EnvironmentVariableTarget.Process);
    }
    
  • 在类中添加[InitializeOnLoad],确保构造函数为run at editor launch

     [InitializeOnLoad]
     public class MyClassWhichUsesPlugin
     {
         ...
         static MyClassWhichUsesPlugin() // static Constructor
         {
             ...
         }
      }
    

使用此脚本,无需复制 DLL。 Unity 编辑器在Assets/.../Plugins/...-文件夹中找到它们,而可执行文件在..._Data/Plugins-目录中找到它们(在构建时它们会自动复制到该目录)。

【讨论】:

  • 我无法让静态在 Unity 2017.3.1f1 中工作。在运行时我得到:“UnityException:get_dataPath 不允许从 MonoBehaviour 构造函数(或实例字段初始化程序)调用,而是在 Awake 或 Start 中调用它。”我将其切换为使用 Awake() 并且在我的构建中运行良好,编辑器和。
  • 这实际上是一个非常优雅的解决方案,它可以在 edtior 模式下使用外部库(用于检查器脚本),这在以“正常”方式执行时并不容易做到。
  • 在我最近的测试(Unity 2019.2)中,似乎插件目录已经添加到PATH,并且静态构造函数似乎不再需要了。其他人可以证实这一点吗?
【解决方案2】:

好吧,我让它工作了。 对于可能遇到此问题的其他人,如果您有多个 dll,则需要将辅助 dll 放在 Unity 编辑器的根级别(例如 C:\Program Files\Unity\Editor),并将脚本中实际引用的 dll 放入插件文件夹。 这对我有用。

【讨论】:

  • DLL 文件的更好位置是在项目文件夹中。只需将 dll 文件放在与“Assets”和“Library”文件夹相同的文件夹中即可。
  • @TrolleFar 这对我有用,为我节省了数小时的头痛,感谢你们发布问题、答案和 cmets!
  • 即使我将 dll 文件放在项目目录和构建后与 exe 文件相同的文件夹中,我仍然会收到这些异常。是否需要 Visual C++ Redistributable?我从 Visual C++ 2008 SP1 构建 dll 并安装了微软网站上可用的所有 Visual C++ 2008 Redistributable 仍然得到在其他机器上找不到的异常 dll。
  • 我尝试了所有这些解决方案几个小时......结果我的外部 DLL 是 32 位的,而我的 Unity 项目是 64 位的。收到DllNotFoundException,所以被带到花园小路上……另一件需要注意的事情。
  • 尝试了一切,没有任何效果。请帮助stackoverflow.com/questions/54898629/…
【解决方案3】:

将 DLL(s) Unity 接口放在 Project\Assets\Wherever\Works\Best\Plugins 中。

将您的脚本不直接访问的任何依赖 DLL 放在 Project 中。这将允许您的程序在编辑器中运行。

当你构建时,再次复制依赖 DLL 文件,这次复制到构建目录的根目录(紧邻生成的可执行文件)。这应该允许您的应用程序在运行时加载它们。

(提示:您可以使用Dependency Walker 查看您的 DLL,看看它们依赖于什么。)

【讨论】:

  • 请注意,如果 dll 是一个托管程序集(假设我有正确的术语),它有一个单独的程序集作为依赖项,第一个程序集可以与依赖项一起进入 Plugins 文件夹并工作在一个构建中。但是,要在编辑器中运行,您需要项目文件夹中的依赖项的副本,如上面对 dll 的描述。
【解决方案4】:

我花了一天时间处理这个错误。我的问题是 Android 没有得到库并且总是得到和 DDLNotFound 错误。我的解决方案是:

1.- 确保您在 Plugins 文件夹中有适用于正确架构的库。

Plugins/Android/x86 和 Plugins/Android/armeabi-v7a 如果您的构建设置为 FAT(x86&arm)

2.- 检查 Unity 是否将它们识别为库。如果您在“项目”选项卡中选择它们,您应该将它们视为一个库,并且与平台和架构相关。

3.- 构建后(不要关闭 Unity 编辑器!),如果您的库在那里,您可以检查 Temp/StagingArea/libs。如果确实存在这些库,那么这些库将在 APK 中。作为仔细检查,您可以打开 APK(更改为 zip 扩展名)并查看 lib 文件夹中的库。

4.- 在 C# 中,您应该删除库名称中的任何 lib 前缀,例如:

如果您的库名称是“libdosomething.so”,您应该将其命名为

[DllImport ("dosomething")]

我希望这对你有用:)

干杯。

【讨论】:

  • 这对我有帮助。我正在使用 Unity 2018.3,正确的架构现在是 Plugins/Android_x86 和 Plugins/Android_armeabi-v7a。我还在 Plugins/Android_arm64-v8a 中放置了一个库,但 Unity 将其识别为 arm64,但未使用它。不支持 Android_x86_64
【解决方案5】:

确保满足以下检查清单:

  • 插件应全部保存在名为 Plugins 的文件夹中。
  • 构建您的 dll 的架构(x86 或 x86_64)必须与 Unity Editor 的架构版本相对应。 Unity Editor 32 位不会加载 64 位插件,反之亦然。
  • 如果您同时针对 32 位和 64 位架构,您应该将您的 dll 放在 Plugins 文件夹内的特殊命名文件夹中。 32 位 dll 的名称是 Plugins/x86,64 位 dll 的名称是 Plugins/x86_64(x64 也可以)。
  • 必须安装 Visual C++ Redistributables。我有 2008 年的所有东西。
  • 在构建时,应将所有 dll 复制到可执行文件所在的根目录中(并再次为正确的 x86/x64 架构构建)

如果您不断收到命名空间错误,则表示您正在导入的 dll 具有非托管代码,并且必须将其包装到另一个托管 dll Pugin 中才能工作。

这些线程有点过时但仍然相关

DLLNotFoundException - Unity3D Plugin

Unity internal compiler error with custom dll

【讨论】:

【解决方案6】:

只需将 dll 放在 Plugins 文件夹下,这对我有用

【讨论】:

  • 现代版本的 Unity 不需要这个
【解决方案7】:

就我而言,我有 DllNotFoundException: ovrplatiformloader

 Unity   : DllNotFoundException: ovrplatformloader
 Unity   :   at (wrapper managed-to-native) Oculus.Platform.CAPI.ovr_UnityInitWrapperAsynchronous(string)
 Unity   :   at Oculus.Platform.AndroidPlatform.AsyncInitialize (System.String appId) [0x00013] in <29065e843b82403894fca6c6f2974090>:0 
 Unity   :   at Oculus.Platform.Core.AsyncInitialize (System.String appId) [0x0004f] in <29065e843b82403894fca6c6f2974090>:0 
 Unity   :   at DBHelper.Start () [0x00019] in <29065e843b82403894fca6c6f2974090>:0 

我的解决办法是:

  1. 重新导入不起作用的文件 (libovrplatformloader.so)
  2. 重构平台/插件架构。 旧版:Platform/Plugins/Android32/libovrplatformloader.so。 :Platform/Plugins/Android/x86/libovrplatformloader.so Platform/Plugins/Android/armeabi-v7a/libovrplatformloader.so
  3. 修改 libovrplatformloader.so 的导入设置。将任何平台更改为仅 Android 平台并启用“启动时加载”选项。在 armeabit-v7a 中选择 ARMv7 CPU,在 x86 文件夹中选择 x86 CPU。

【讨论】:

    【解决方案8】:

    我遇到了同样的问题,这里描述的解决方案不起作用。 我觉得我的情况有点不同。 我认为我正在导入的 .dll 依赖于其他 .dll 文件。所以我导入了与该 .dll 相关的其他文件(我认为这是不必要的,因为我没有直接在 c# 代码上调用它们)并且解决了这个问题。

    【讨论】:

      猜你喜欢
      • 2015-07-21
      • 2015-10-25
      • 2011-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多