为什么 Unity 在链接到 OpenCV 时无法加载 android 本机库?
Why does Unity fail to load android native libraries when linked against OpenCV?
标题说明了一切。我正在使用 NDK 构建用于 Unity 的本机库(游戏引擎,而不是 Ubuntu shell)。我已经有了很多代码,它可以在我的 Xperia Z Ultra 运行s Android 4.4.4 上运行。但是,最近我将该应用程序发送给其他一些人以在他们的手机上进行测试,并且它可以在他们的 none 部手机上运行。他们使用 Android 4.0 和 4.1,所以我尝试 运行 在我自己的 Android 4.0.4 设备(旧的 Xperia Mini Pro)上安装该应用程序,但遇到了同样的问题。在缩小范围之后,我发现问题的根源是在构建中包含 OpenCV,即使它根本没有被引用。
这是我现在的代码。一、你见过的最简单的CPP文件:
//Test.cpp:
extern "C"
{
int Test(int a, int b)
{
return a + b;
}
}
请注意它甚至不包含来自 OpenCV 的任何内容。生成文件(或在 NDK 上下文中的任何名称,我主要是 Windows/Visual Studio 人员)是:
#Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#---------------------------
#note: if I comment these lines out, the library works just fine.
#if I don't, it won't load at all.
#---------------------------
OPENCV_PACKAGE_DIR := D:\Eclipse\OpenCVAndroid\OpenCV-2.4.9-android-sdk
include $(OPENCV_PACKAGE_DIR)/sdk/native/jni/OpenCV.mk
LOCAL_MODULE := Test
LOCAL_SRC_FILES := Test.cpp
include $(BUILD_SHARED_LIBRARY)
构建这个项目给我一个 "libTest.so" 文件。我将其放入我的 Unity 项目中,位于 Assets/Plugins/Android/(我也尝试将其放入 Plugins/Android/libs/armeabi-v7a/,但没有成功)。我在 unity 中也有一个调用库的脚本:
//TestNative.cs:
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class TestNative : MonoBehaviour
{
[DllImport("Test")]
public static extern int Test(int a, int b);
void OnGUI()
{
try
{
GUI.Label(new Rect(0, 0, 100, 100), "2 + 3 = " + Test(2, 3));
}
catch (System.Exception e)
{
GUI.Label(new Rect(0, 0, 600, 400), e.GetType().ToString() + " " + e.Message + "\n" + e.StackTrace);
}
}
}
当我在我的 Z Ultra 上 运行 时,它工作得很好。当我在 Mini Pro 上 运行 它时,它失败了 "DllNotFoundException: Test"。我检查了 logcat 是否有错误,它是这样说的:
01-06 06:46:27.660: D/dalvikvm(11135): Trying to load lib /mnt/asec/com.cet.sna2-2/lib/libTest.so 0x2bb86638
01-06 06:46:27.660: D/dalvikvm(11135): Trying to load lib /mnt/asec/com.cet.sna2-2/lib/libTest.so 0x2bb86638
01-06 06:46:27.660: E/Unity(11135): Unable to find Test
它什么也没说,就是失败了。它在 4.4.4 上运行的事实让我认为它可能与构建配置或类似的东西有关,但我无法弄清楚它是什么。有任何想法吗?谢谢。
您必须构建一个与您正在使用的设备的体系结构相对应的 .so。
你应该看看这个 link :
https://developer.nvidia.com/AndroidWorks
它提供了在 Android 和 Visual Studio 上进行开发的有用工具
您可以轻松地配置一个 Android 动态库 (.so) 来对应您需要的架构 :)
经过反复试验,我发现错误的原因是 Android 以某种方式设法弄乱了库依赖项。解决方法是使用 LoadLibrary 以依赖项的特定顺序手动加载库。这可以在 Unity 中使用 AndroidJavaClass 来完成,以避免仅为加载本机库而编写整个 jar 库。
标题说明了一切。我正在使用 NDK 构建用于 Unity 的本机库(游戏引擎,而不是 Ubuntu shell)。我已经有了很多代码,它可以在我的 Xperia Z Ultra 运行s Android 4.4.4 上运行。但是,最近我将该应用程序发送给其他一些人以在他们的手机上进行测试,并且它可以在他们的 none 部手机上运行。他们使用 Android 4.0 和 4.1,所以我尝试 运行 在我自己的 Android 4.0.4 设备(旧的 Xperia Mini Pro)上安装该应用程序,但遇到了同样的问题。在缩小范围之后,我发现问题的根源是在构建中包含 OpenCV,即使它根本没有被引用。
这是我现在的代码。一、你见过的最简单的CPP文件:
//Test.cpp:
extern "C"
{
int Test(int a, int b)
{
return a + b;
}
}
请注意它甚至不包含来自 OpenCV 的任何内容。生成文件(或在 NDK 上下文中的任何名称,我主要是 Windows/Visual Studio 人员)是:
#Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#---------------------------
#note: if I comment these lines out, the library works just fine.
#if I don't, it won't load at all.
#---------------------------
OPENCV_PACKAGE_DIR := D:\Eclipse\OpenCVAndroid\OpenCV-2.4.9-android-sdk
include $(OPENCV_PACKAGE_DIR)/sdk/native/jni/OpenCV.mk
LOCAL_MODULE := Test
LOCAL_SRC_FILES := Test.cpp
include $(BUILD_SHARED_LIBRARY)
构建这个项目给我一个 "libTest.so" 文件。我将其放入我的 Unity 项目中,位于 Assets/Plugins/Android/(我也尝试将其放入 Plugins/Android/libs/armeabi-v7a/,但没有成功)。我在 unity 中也有一个调用库的脚本:
//TestNative.cs:
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class TestNative : MonoBehaviour
{
[DllImport("Test")]
public static extern int Test(int a, int b);
void OnGUI()
{
try
{
GUI.Label(new Rect(0, 0, 100, 100), "2 + 3 = " + Test(2, 3));
}
catch (System.Exception e)
{
GUI.Label(new Rect(0, 0, 600, 400), e.GetType().ToString() + " " + e.Message + "\n" + e.StackTrace);
}
}
}
当我在我的 Z Ultra 上 运行 时,它工作得很好。当我在 Mini Pro 上 运行 它时,它失败了 "DllNotFoundException: Test"。我检查了 logcat 是否有错误,它是这样说的:
01-06 06:46:27.660: D/dalvikvm(11135): Trying to load lib /mnt/asec/com.cet.sna2-2/lib/libTest.so 0x2bb86638
01-06 06:46:27.660: D/dalvikvm(11135): Trying to load lib /mnt/asec/com.cet.sna2-2/lib/libTest.so 0x2bb86638
01-06 06:46:27.660: E/Unity(11135): Unable to find Test
它什么也没说,就是失败了。它在 4.4.4 上运行的事实让我认为它可能与构建配置或类似的东西有关,但我无法弄清楚它是什么。有任何想法吗?谢谢。
您必须构建一个与您正在使用的设备的体系结构相对应的 .so。 你应该看看这个 link : https://developer.nvidia.com/AndroidWorks 它提供了在 Android 和 Visual Studio 上进行开发的有用工具 您可以轻松地配置一个 Android 动态库 (.so) 来对应您需要的架构 :)
经过反复试验,我发现错误的原因是 Android 以某种方式设法弄乱了库依赖项。解决方法是使用 LoadLibrary 以依赖项的特定顺序手动加载库。这可以在 Unity 中使用 AndroidJavaClass 来完成,以避免仅为加载本机库而编写整个 jar 库。