【问题标题】:android ndk UnsatisfiedLinkError when using a prebuilt shared libraryandroid ndk UnsatisfiedLinkError 使用预建共享库时
【发布时间】:2011-07-15 01:29:58
【问题描述】:

我正在尝试创建一个链接到另一个共享库的共享库。

这是我的主模块 Android.mk:

TOP_LOCAL_PATH := $(call my-dir)
include $(call all-subdir-makefiles)

LOCAL_PATH := $(TOP_LOCAL_PATH)

include $(CLEAR_VARS)

LOCAL_CPP_EXTENSION := cpp


LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ $(LOCAL_PATH)/lib/include
LOCAL_MODULE    := SightCore-jni
LOCAL_SRC_FILES := SightDemo.cpp SightCore-jni.cpp
LOCAL_SHARED_LIBRARIES := SightAPI
LOCAL_LDLIBS = -llog 

include $(BUILD_SHARED_LIBRARY)

我在 ./lib 目录中也有预构建的共享库,它有自己的 Android.mk 文件:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := SightAPI
LOCAL_SRC_FILES := libSightAPI.so
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include

include $(PREBUILT_SHARED_LIBRARY)

SightCore-jni.cpp源文件是共享库的jni接口,使用命令加载

System.loadLibrary("SightCore-jni");  

在 ndk-build 过程中,我得到没有编译或链接错误。 当我尝试运行应用程序并访问其中一种本机方法时,我得到了 UnsatsfiedLinkError。 我注意到,如果在我的 jni 代码中禁用对 SightAPI 的引用并在 LOCAL_STATIC_LIBRARIES := SightAPI 行中输入错字,则构建成功并且没有 UnsatisfiedLinkError
这意味着我拥有的jni代码是好的(我实际上确定它是好的......)

所以观察如下:
如果我用预建的共享库编译共享库,我会得到一个损坏的 .so 文件。

如果我编译相同的 ndk 项目没有链接到预建的共享库,则 没问题 从 java 端加载共享库。

如果可以的话,请帮帮我。

提前致谢,

意大利

【问题讨论】:

  • 您在 logcat 中看到什么错误消息?应该是 UnsatisfiedLinkError 异常上方的消息,可能带有 dlopen() 的输出。另外,您使用的是什么版本的 Android?
  • 如何将我的共享库链接到 Android NDK 项目你能解释一下吗

标签: android shared-libraries android-ndk


【解决方案1】:

这发生在我身上,我的解决方案是确保在切换编译器后包含正确的文件 libgnustl_shared.so 而不是 libc++_shared.so。因此,只要确保这些文件中的任何一个是您构建的正确文件,并确保它已更新为最新版本,您就不会再遇到此问题了。

【讨论】:

    【解决方案2】:
    1. 您是否确定要通过 JNI 使用的 cpp 函数名称与存在 System.loadLibrary("SightCore-jni"); 的 Java 包装类的包名称相对应?

      例如如果你想在java层使用C函数myFunction,并假设你的JNI包装类在包com.my.package.sightcore中, 那么你的 C 代码函数名应该是这样的:

       JNIEXPORT  JNICALL Java_com_my_package_sightcore_myFunction(JNIEnv * env, jobject thiz, ...)
      
    2. 如果您在设备上运行应用, 查看 API 级别,因此,sdk 版本是否与您设备的 android 版本(API 级别)匹配。

    希望这会有所帮助。如果您需要更多说明,请告诉我...

    【讨论】:

    • 参考这个优秀的教程,这可能会有所帮助:mindtherobot.com/blog/452/…
    • 如果我们有一个最初不是为在 JNI 环境中使用而设计的 .so 文件会发生什么。这个库的方法不会有 javah 命令创建的将包名和类名应用于函数的命名约定。这将如何解决?谢谢
    • 据我所知,如果.so文件没有正确的命名约定,即JNI命名方案,它不会被“导出”到java级别。因此不能使用。您必须获取该库的源代码,并使用正确的命名约定构建它,以便在 Java 层可以看到它以供使用。希望这会有所帮助。
    • 如果您无法获得原件的来源,一个简单的解决方案是编写一个库,将原件包装在函数中,其名称与 jni 约定匹配。
    【解决方案3】:

    发现问题。

    显然,ndk 构建系统不会自动加载引用的共享库,即使它们已在您的 Android.mk 中声明。

    我不得不致电System.loadLibrary(SightAPI) & System.loadLibrary("SightCore-jni") 来解决这个问题。我原以为要加载的唯一库是主库 SightCore-jni

    嗯..我想道德是如果你想做某事,就自己做吧:)

    +1 感谢 Roy Samuel 的努力和正确的直觉。

    我希望这对任何人都有帮助。

    干杯

    【讨论】:

    • 我必须把这个 System.loadLibrary(SightAPI) 放在 static{ }.?并使用“SightAPI”?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-20
    • 1970-01-01
    • 1970-01-01
    • 2015-03-27
    • 2015-07-11
    • 2011-09-04
    相关资源
    最近更新 更多