Unity 中的原生 Android 库抛出 DllNotFound 异常
Native Android library in Unity throws DllNotFound exception
我用 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
这是我的设置和脚本:
基于 here and here,我在我的 Assets 中创建了 Plugins
文件夹,并像这样放置我的库:
Plugins
|_ Android
| |_ libs
| |_ armeabi-v7a
| | |_ libMatinChess.so
| |_ x86
| |_ libMatinChess.so
|_ x64
| |_ MatinChess.dll
|_ x86
|_ MatinChess.dll
而且我确定 Inspector 中的 Platform Settings 配置正确。
我在我的脚本中使用了我的库并基于 here and here,而不是将 libMatinChess.so
用于 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 编辑器。
可能会在 Environment.SetEnvironmentVariable("PATH",...)
之前调用方法 MatinChess.Net.ExternMethods.Initialize
,这会导致 DllNotFoundException。
在调用 MatinChess.Net.ExternMethods.Initialize
和 Environment.SetEnvironmentVariable
之前尝试打印日志消息。然后你可以检查这些方法的调用顺序。
如果这是原因,请添加,将 Environment.SetEnvironmentVariable("PATH",...)
移动到 MatinChess.Net.ExternMethods
的静态初始值设定项可能会解决您的问题。
编辑:
设置后尝试打印PATH
,方法可能设置失败
编辑:
只是猜测.. android 共享库搜索路径应该是 LD_LIBRARY_PATH
而不是 PATH
。尝试设置它。我不确定 Unity3D 是否处理了这个问题。
编辑:
除了 libMatinChess.so
之外,不包括所有库依赖项是一个可能的原因。一些信息 here.
目前能想到的就这些了
检查您是否确实导出了具有正确符号的有效 .so 文件。
还要检查您是否包含了 libMatinChess.so
的所有库依赖项,有时可能包括您的 C 运行时。尝试与标准库静态链接。
我用 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
这是我的设置和脚本:
基于 here and here,我在我的 Assets 中创建了 Plugins
文件夹,并像这样放置我的库:
Plugins
|_ Android
| |_ libs
| |_ armeabi-v7a
| | |_ libMatinChess.so
| |_ x86
| |_ libMatinChess.so
|_ x64
| |_ MatinChess.dll
|_ x86
|_ MatinChess.dll
而且我确定 Inspector 中的 Platform Settings 配置正确。
我在我的脚本中使用了我的库并基于 here and here,而不是将 libMatinChess.so
用于 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 编辑器。
可能会在 Environment.SetEnvironmentVariable("PATH",...)
之前调用方法 MatinChess.Net.ExternMethods.Initialize
,这会导致 DllNotFoundException。
在调用 MatinChess.Net.ExternMethods.Initialize
和 Environment.SetEnvironmentVariable
之前尝试打印日志消息。然后你可以检查这些方法的调用顺序。
如果这是原因,请添加,将 Environment.SetEnvironmentVariable("PATH",...)
移动到 MatinChess.Net.ExternMethods
的静态初始值设定项可能会解决您的问题。
编辑:
设置后尝试打印PATH
,方法可能设置失败
编辑:
只是猜测.. android 共享库搜索路径应该是 LD_LIBRARY_PATH
而不是 PATH
。尝试设置它。我不确定 Unity3D 是否处理了这个问题。
编辑:
除了 libMatinChess.so
之外,不包括所有库依赖项是一个可能的原因。一些信息 here.
目前能想到的就这些了
检查您是否确实导出了具有正确符号的有效 .so 文件。
还要检查您是否包含了 libMatinChess.so
的所有库依赖项,有时可能包括您的 C 运行时。尝试与标准库静态链接。