Unity中的原生Android库抛出DllNotFound异常

时间:2016-11-23 13:16:15

标签: android c++ unity3d mono native

我用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,我在资产中创建了Plugins文件夹,并按照以下方式放置了我的库:

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

我确信我的检查器中的平台设置已正确配置。

我在我的脚本中使用了我的库并基于herehere,而不是使用libMatinChess.so for Android,我没有在开始时使用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 Editor。

2 个答案:

答案 0 :(得分:0)

方法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

以上是我现在所能想到的。

答案 1 :(得分:0)

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

同时检查您是否已包含<!--#include virtual="footer.ssi" -->的所有库依赖项,有时可能包含C运行时。尝试静态链接标准库。