在Android NDK中链接共享库

8
我成功地将LibXtract库编译为共享对象libxtract.so,并希望在第二个项目中使用它。
在该项目中,我尝试编译一个简单的函数:
#include <com_androidnative1_NativeClass.h>
#include <android/log.h>
#include "libxtract.h"

JNIEXPORT void JNICALL Java_com_androidnative1_NativeClass_showText
(JNIEnv *env, jclass clazz)
{

    float mean = 0, vector[] = {.1, .2, .3, .4, -.5, -.4, -.3, -.2, -.1}, spectrum[10];
    int n, N = 9;
    float argf[4];

    argf[0] = 8000.f;
    argf[1] = XTRACT_MAGNITUDE_SPECTRUM;
    argf[2] = 0.f;
    argf[3] = 0.f;

    xtract[XTRACT_MEAN]((void *)&vector, N, 0, (void *)&mean);
    __android_log_print(ANDROID_LOG_DEBUG, "LIbXtract", "Button pushe2");
}

我有一个扁平的结构:

  • jni/com_androidnative1_NativeClass.c
  • jni/com_androidnative1_NativeClass.hjni/libxtract.h
  • jni/libxtract接口中的其它*.h文件
  • jni/Android.mk
  • jni/Applicatoin.mk

我将库libxtract.so放在mainproject/lib文件夹中。

我的Android.mk文件看起来像这样:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := com_androidnative1_NativeClass.c 
LOCAL_MODULE := com_androidnative1_NativeClass
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/
LOCAL_LDLIBS += -llog
LOCAL_SHARE_LIBRARIES := libxtract
NDK_MODULE_PATH += $(LOCAL_PATH)/../lib/
include $(BUILD_SHARED_LIBRARY)

我仍然遇到错误:


Compile thumb  : com_androidnative1_NativeClass <= com_androidnative1_NativeClass.c
SharedLibrary  : libcom_androidnative1_NativeClass.so./obj/local/armeabi/objs/com_androidnative1_NativeClass/com_androidnative1_Nativ    eClass.o: In function `Java_com_androidnative1_NativeClass_showText':
/home/jack/Projects/AndroidNative1/jni/com_androidnative1_NativeClass.c:20: undefined reference to `xtract'
collect2: ld returned 1 exit status
make: *** [obj/local/armeabi/libcom_androidnative1_NativeClass.so] Error 1

这段代码来自于LibXtract的示例,经过C++编译没有问题,您有什么想法吗?


你是如何编译libxtract.so的?为什么不将其编译添加到同一个Android.mk文件中,这样两个共享库就可以同时构建了呢? - Mārtiņš Možeiko
1
我采用了这个解决方案链接进行编译,只需添加共享库即可保持简单。 - Jack
1
这个回答看起来像是解决了你的问题。https://dev59.com/mWPVa4cB1Zd3GeqP9de4#10615769 - codetiger
可能是如何将预构建的共享库链接到Android NDK项目?的重复问题。 - Ciro Santilli OurBigBook.com
3个回答

5

你的Android makefile应该是...

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LIB_PATH := $(LOCAL_PATH)/../lib
LOCAL_SRC_FILES := com_androidnative1_NativeClass.c 
LOCAL_MODULE := com_androidnative1_NativeClass
LOCAL_LDLIBS += -llog

LOCAL_LDLIBS += $(LIB_PATH) -lxtract

LOCAL_SHARE_LIBRARIES := libxtract
include $(BUILD_SHARED_LIBRARY)

尝试在您的第二个项目中使用此make文件,即可成功地构建您的代码,而不会出现任何错误。

我使用了你和@FooF的解决方案,我的Android.mk文件如下:LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libxtract LOCAL_SRC_FILES := libxtract.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LIB_PATH := $(LOCAL_PATH)/../lib/libxtract.so LOCAL_SRC_FILES := com_androidnative1_NativeClass.c LOCAL_MODULE := com_androidnative1_NativeClass LOCAL_LDLIBS += -llog LOCAL_LDLIBS += $(LIB_PATH) LOCAL_SHARE_LIBRARIES := libxtract include $(BUILD_SHARED_LIBRARY) - Jack
代码已经成功构建,但是当我运行使用它的代码时,出现了错误: 06-04 21:58:26.504: E/AndroidRuntime(14792): Caused by: java.lang.UnsatisfiedLinkError: Couldn't load libxtract: findLibrary returned null 当然我使用了 System.loadLibrary("libxtract"); - Jack
在成功构建libxtract.so后,请在您的第二个项目中使用此makefile。LIB_PATH应该是正确的。在您的第二个项目makefile中使用'LOCAL_LDLIBS + = $(LIB_PATH)-lxtract',否则您将获得上述错误。 - Suvam Roy
1
LOCAL_SHARE_LIBRARIES => LOCAL_SHARED_LIBRARIES - kid

3
在上面的答案中,除了一个小错误外都是正确的。
当我们想要链接库时,我们必须在LOCAL_LDLIBS目录之前加上-L,如下所示。
LIB_PATH := $(LOCAL_PATH)/../lib

LOCAL_LDLIBS += **-L**$(LIB_PATH) -lxtract

否则它会出现以下错误:

无法打开XXX/../lib: 权限被拒绝


2
你能澄清一下你所参考的答案是哪一个吗? - James Jenkins
将共享库包含在搜索路径中的语法。1)必须通过-L指令指定路径,然后2)立即通过-l指令指定要共享的库。 - drlolly

2

您需要告诉Android NDK构建脚本关于您的共享库。请查看${NDK}/doc/PREBUILTS.html以了解如何完成此操作。他们建议在与libXtract.so相同的目录中添加Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libXtract
LOCAL_SRC_FILES := libXtract.so
include $(PREBUILT_SHARED_LIBRARY)

调试技巧:我猜测你正在使用ndk-build来构建你的“第二个项目”。尝试使用V=99运行ndk-build(尝试V=99 ndk-buildndk-build V=99 - 我的记忆有些模糊)。这将显示出确切失败的链接命令。你应该有选项-lXtract-L/path/to/libXtract/library。(有时候,只需复制并粘贴链接命令手动运行它以找到成功链接的正确选项,然后才实际修正构建设置更为方便。)
更新:我现在看到@codetiger的评论似乎指向了同样的答案(没有提到NDK文档,这是很好的阅读材料-所以我不会删除这个答案)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接