【问题标题】:Native Android library in Unity throws DllNotFound exceptionUnity 中的原生 Android 库引发 DllNotFound 异常
【发布时间】:2016-11-23 13:16:15
【问题描述】:

我用 C++ 编写了一个国际象棋库,并为 Windows(32 位和 64 位)和 Android(x86 和 armebi-v7)编译了它。

我的 Windows 构建完全正确,但是当我为 Android 构建它并运行游戏时,我的adb logcat -s Unity 收到以下异常:

11-23 16:39:37.278 22335 22352 I Unity   : DllNotFoundException: MatinChess
11-23 16:39:37.278 22335 22352 I Unity   :   at (wrapper managed-to-native) MatinChess.Net.ExternMethods:Initialize ()
11-23 16:39:37.278 22335 22352 I Unity   :   at MatinChess.Net.MatinChess..ctor () [0x00000] in <filename unknown>:0
11-23 16:39:37.278 22335 22352 I Unity   :   at Model.Awake () [0x00000] in <filename unknown>:0

当我解压缩我的 apk 文件时,我有:

lib
|_ armeabi-v7a
|  |_ libmain.so
|  |_ libMatinChess.so
|  |_ libmono.so
|  |_ libunity.so
|_ x86
   |_ libmain.so
   |_ libMatinChess.so
   |_ libmono.so
   |_ libunity.so

这是我的设置和脚本:

基于herehere,我在我的Assets 中创建了Plugins 文件夹,并像这样放置我的库:

Plugins
|_ Android
|  |_ libs
|     |_ armeabi-v7a
|     |  |_ libMatinChess.so
|     |_ x86
|        |_ libMatinChess.so
|_ x64
|  |_ MatinChess.dll
|_ x86
   |_ MatinChess.dll

我确定我的 Inspector 中的 Platform Settings 配置正确。

我在我的脚本中使用了我的库并基于herehere,而不是在Android 上使用libMatinChess.so,我在开始时没有使用lib,最后没有使用.so。所以是这样的:

class ExternMethods
{
#if UNITY_ANDROID
    const string dll = "MatinChess";
#else
    const string dll = "MatinChess.dll";
#endif

    [DllImport(dll, CallingConvention = CallingConvention.Cdecl)]
    public extern static PlayState CheckState();

    [DllImport(dll, CallingConvention = CallingConvention.Cdecl)]
    public extern static void Initialize();

    //
    // other extern methods
    //
}

因此,当我为 Windows 构建 Unity 游戏时,它可以正常工作。为了让它在编辑器中工作,我关注了this link,并编写了以下脚本:

public class Model : MonoBehaviour
{    
    void Awake()
    {
#if UNITY_EDITOR_32
        var dllPath = Application.dataPath + Path.DirectorySeparatorChar + "Plugins" + Path.DirectorySeparatorChar + "x32";
#elif UNITY_EDITOR_64
        var dllPath = Application.dataPath + Path.DirectorySeparatorChar + "Plugins" + Path.DirectorySeparatorChar + "x64";
#else // Player
        var dllPath = Application.dataPath + Path.DirectorySeparatorChar + "Plugins";
#endif
        var currentPath = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Process);
        if (currentPath != null && currentPath.Contains(dllPath) == false)
            Environment.SetEnvironmentVariable("PATH", currentPath + Path.PathSeparator + dllPath, EnvironmentVariableTarget.Process);
    }
}

所以它也适用于 Unity 编辑器。

【问题讨论】:

  • 为什么要为 Android 配置 .dll 文件,因为您已经拥有 .so 文件?
  • @PravinD 我想说我的使用 .dll 配置的 Windows 构建工作正常,但具有 .so 配置的 Android 却不行。并告知您我的配置差异。
  • 您使用的是哪个版本的 Unity3D?
  • @zwcloud 版本为 5.4.1f1 个人版

标签: android c++ unity3d mono native


【解决方案1】:

检查您是否确实导出了具有正确符号的有效 .so 文件。

还要检查您是否包含了 libMatinChess.so 的所有库依赖项,其中有时可能包括您的 C 运行时。尝试与标准库进行静态链接。

【讨论】:

    【解决方案2】:

    MatinChess.Net.ExternMethods.Initialize 方法可能在 Environment.SetEnvironmentVariable("PATH",...) 之前被调用,这会导致 DllNotFoundException。

    在致电MatinChess.Net.ExternMethods.InitializeEnvironment.SetEnvironmentVariable 之前尝试打印一条日志消息。然后你可以检查这些方法的调用顺序。

    添加如果这是原因,将 Environment.SetEnvironmentVariable("PATH",...) 移动到 MatinChess.Net.ExternMethods 的静态初始化程序可能会解决您的问题。

    编辑:
    设置好PATH后尝试打印,方法可能设置失败。

    编辑:
    只是猜测.. android 共享库搜索路径应该是LD_LIBRARY_PATH 而不是PATH。尝试设置它。我不确定 Unity3D 是否处理过这个问题。

    编辑:
    除了 libMatinChess.so 之外,不包括所有库依赖项是可能的原因。一些信息here.

    以上就是我现在能想到的了。

    【讨论】:

    • 不。之后我调用 Initialize。
    • 你查看过android平台的日志吗?顺序是否正确?
    • 我已经测试了你们所有的两个编辑。我还在我的 adb shell 中找到了我的 .so,但仍然是 dllnotfound 异常。
    • 我现在能想到的就这么多了,抱歉。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-12
    • 2016-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多