我用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和here,我在资产中创建了Plugins
文件夹,并按照以下方式放置了我的库:
Plugins
|_ Android
| |_ libs
| |_ armeabi-v7a
| | |_ libMatinChess.so
| |_ x86
| |_ libMatinChess.so
|_ x64
| |_ MatinChess.dll
|_ x86
|_ MatinChess.dll
我确信我的检查器中的平台设置已正确配置。
我在我的脚本中使用了我的库并基于here和here,而不是使用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。
答案 0 :(得分:0)
方法MatinChess.Net.ExternMethods.Initialize
可能会在Environment.SetEnvironmentVariable("PATH",...)
之前调用,从而导致DllNotFoundException。
在致电MatinChess.Net.ExternMethods.Initialize
和Environment.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运行时。尝试静态链接标准库。