我最近开始使用NDK并遇到问题。我基本上想在我的应用程序中使用外部静态库(.so)。这是我到现在为止所尝试过的。
1)在Java类中添加一个带有native关键字
的方法public native static void FibNR ();
2)在终端导航到项目文件夹并运行以下命令
mkdir jni
javah -jni -classpath bin/classes/ -d jni/ com.example.fibonaccinative.FibLib
3)刷新项目并添加与生成的H文件对应的C文件。
4)在JNI文件夹中创建一个Android.mk文件,并在其中添加以下代码
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_LIB_TYPE :=STATIC
LOCAL_SRC_FILES := com_example_fibonaccinative_FibLib.c
LOCAL_MODULE := com_example_fibonaccinative_FibLib
include $(BUILD_SHARED_LIBRARY)
5)使用以下命令构建代码
/Developer/android-ndk-r9b/ndk-build all
以上步骤成功执行,我也可以查看c代码的结果。现在我想创建一个新的应用程序并使用生成的.so文件(com_example_fibonaccinative_FibLib.so)。为此我做了以下
按照上面的步骤1,2和3进行新申请
4)在JNI文件夹中创建一个Android.mk文件,并在其中添加以下代码
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_LIB_TYPE :=STATIC
LOCAL_SRC_FILES := com_example_usingstaticlibrary_LibraryTest.c
LOCAL_MODULE := com_example_usingstaticlibrary_LibraryTest
LOCAL_SHARED_LIBRARIES :=libcom_example_fibonaccinative_FibLib.so
LOCAL_LDLIBS := -L$(SYSROOT)/usr -llog
include $(BUILD_SHARED_LIBRARY)
5)使用以下命令构建代码
/Developer/android-ndk-r9b/ndk-build all
我不知道下一步该做什么。我认为我需要将库的功能调用到com_example_usingstaticlibrary_LibraryTest.c中。但这样做会给我一个错误说
'com_example_fibonaccinative_FibLib'undeclared
编辑1:
1)在项目2中(我想使用预建的共享库(.so))我将库复制到'jni'文件夹
2)使用以下文本更改了Android.mk文件。
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libcom_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := libcom_example_fibonaccinative_FibLib.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := com_example_usingstaticlibrary_LibraryTest
LOCAL_SHARED_LIBRARIES := libcom_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := com_example_usingstaticlibrary_LibraryTest.c
include $(BUILD_SHARED_LIBRARY)
3)将旧项目中的.h文件(com_example_fibonaccinative_FibLib.h)添加到'jni'文件夹中
4)将com_example_usingstaticlibrary_LibraryTest.c的来源更改为
#include "com_example_usingstaticlibrary_LibraryTest.h"
#include "com_example_fibonaccinative_FibLib.h"
JNIEXPORT jlong JNICALL Java_com_example_usingstaticlibrary_LibraryTest_callLibraryFunction
(JNIEnv *env, jclass class) {
Java_com_example_fibonaccinative_FibLib_fibNR(env, class, 500l);
return -500l;
}
清理/构建结果为以下错误
undefined reference to 'Java_com_example_fibonaccinative_FibLib_fibNR'
编辑2:
参考this我编辑了Android.mk,如下所示
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := com_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := libcom_example_fibonaccinative_FibLib.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := com_example_usingstaticlibrary_LibraryTest
LOCAL_SRC_FILES := com_example_usingstaticlibrary_LibraryTest.c
LOCAL_SHARED_LIBRARIES := com_example_fibonaccinative_FibLib
include $(BUILD_SHARED_LIBRARY)
NDK构建命令无错误地编译代码。尝试加载库时,它会出现以下错误
Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/example/usingstaticlibrary/LibraryTest
当我删除LOCAL_SHARED_LIBRARIES := com_example_fibonaccinative_FibLib
时,它工作正常,但我无法使用Prebuilt共享库的任何功能。
编辑3:
我尝试了一些更多的东西,包括@jcm的建议,但没有任何效果。我现在附上source code。它有两个项目(Cleaned version to reduce size)。
答案 0 :(得分:4)
您说要包含预编译的静态库 .a ,但您引用的文件是共享库 .so 。如果你仍然想要包含一个静态库,那么解决方案和解释就是:
LOCAL_SHARED_LIBRARIES :=libcom_example_fibonaccinative_FibLib.so
您尝试将静态库作为共享库包含在内,看起来像是使用以前的共享库条目作为参考的偶然漏洞:)。
在此之后,Android makefile仍然要求您实际为外部库创建模块。
include $(CLEAR_VARS)
LOCAL_MODULE := com_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := com_example_fibonaccinative_FibLib.a
include $(PREBUILT_STATIC_LIBRARY)
然后您可以简单地将其添加为依赖项:
LOCAL_STATIC_LIBRARIES := com_example_fibonaccinative_FibLib
但是如果你真的想要包含一个外部共享库。您需要将以上内容更改为以下内容:
include $(CLEAR_VARS)
LOCAL_MODULE := com_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := com_example_fibonaccinative_FibLib.so
include $(PREBUILT_SHARED_LIBRARY)
并将其包含为共享库。
LOCAL_SHARED_LIBRARIES := com_example_fibonaccinative_FibLib
希望我帮忙!
免责声明:我实际上并没有尝试编写一个例子,只是简单地引用我的知识和快速研究。
参考文献: Android NDK: Static library used is different than precompiled library specified
答案 1 :(得分:1)
当您将libcom_example_fibonaccinative_FibLib.so作为LibraryTest的共享库包含在java静态方法中时,您应该在加载LibraryTest之前加载它:
System.loadlibrary(com_example_fibonaccinative_FibLib);
System.loadLibrary(LibraryTest);
更新
检查完代码后,LibraryTest.java应如下所示:
package com.kochartech.usingstaticlibrary;
public class LibraryTest {
public native static long callLibraryFunction();
static {
System.loadLibrary("com_kochartech_fibonaccinative_FibLib");
System.loadLibrary("com_kochartech_usingstaticlibrary_LibraryTest");
}
}