我正试图运行并理解这个例子:http://answers.oreilly.com/topic/2689-how-to-use-the-android-ndk-to-improve-performance/
这是一个非常简单的例子,包含以下文件:
FibActivity.java - main activity file
FibLib - class implementing and calling the native functions
fib.c - the C source file with the native functions and code
FibLib.h - the C header file, automatically created from the FibLib class
Android.mk - the makefile
我完全按照描述实现了这个例子。不过,当我运行它时,当应用程序尝试访问本机代码时,我会收到此(UnsatisfiedLinkError)错误:
12-21 11:31:53.042: D/dalvikvm(1491): Trying to load lib /data/data
/com.frank.android.ndk/lib/libfib.so 0x405143b8
12-21 11:31:53.042: D/dalvikvm(1491): Added shared lib /data/data/com.frank.android.ndk
/lib/libfib.so 0x405143b8
12-21 11:31:53.042: D/dalvikvm(1491): No JNI_OnLoad found in /data/data
/com.frank.android.ndk/lib/libfib.so 0x405143b8, skipping init
12-21 11:31:53.093: W/dalvikvm(1491): No implementation found for native Lcom/frank
/android/ndk/FibLib;.fibN (I)J
12-21 11:31:53.102: D/AndroidRuntime(1491): Shutting down VM
12-21 11:31:53.102: W/dalvikvm(1491): threadid=1: thread exiting with uncaught
exception (group=0x40015560)
12-21 11:31:53.112: E/AndroidRuntime(1491): FATAL EXCEPTION: main
12-21 11:31:53.112: E/AndroidRuntime(1491): java.lang.UnsatisfiedLinkError: fibN
12-21 11:31:53.112: E/AndroidRuntime(1491): at
com.frank.android.ndk.FibLib.fibN(Native Method)
12-21 11:31:53.112: E/AndroidRuntime(1491): at
com.frank.android.ndk.JavaNativeFibonacciAct
ivity.onClick(JavaNativeFibonacciActivity.java:52)
我注意到的唯一奇怪的事情是,根据logcat,eclipse试图从/ lib文件夹加载库,而自动创建的文件夹名为/ libs。但是,将/ lib文件夹重命名为/ libs并重建所有内容没有任何区别。
有人有任何想法吗?我一直在尝试使用javah创建头文件的示例。仅创建主活动和c文件,然后从主活动调用本机代码似乎可行,但是一旦我开始使用头文件,我就会得到UnsatisfiedLinkError。
更新:
来自FibLib.java:
// Native implementation
static {
System.loadLibrary("fib"); //
}
// Native implementation - recursive
public static native long fibN (int n);
// Native implementation - iterative
public static native long fibNI (int n);
fib.c文件:
#include "com_frank_android_ndk_FibLib.h" /* */
/* Recursive Fibonacci Algorithm */
long fibN(long n) {
if(n<=0) return 0;
if(n==1) return 1;
return fibN(n-1) + fibN(n-2);
}
/* Iterative Fibonacci Algorithm */
long fibNI(long n) {
long previous = -1;
long result = 1;
long i=0;
int sum=0;
for (i = 0; i <= n; i++) {
sum = result + previous;
previous = result;
result = sum;
}
return result;
}
/* Signature of the JNI method as generated in header file */
JNIEXPORT jlong JNICALL Java_com_frank_android__ndk_fibN (JNIEnv *env, jclass obj, jlong n) {
return fibN(n);
}
/* Signature of the JNI method as generated in header file */
JNIEXPORT jlong JNICALL Java_com_frank_android__ndk_fibNI (JNIEnv *env, jclass obj, jlong n) {
return fibNI(n);
}
Andoid.mk文件:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := fib
LOCAL_SRC_FILES := fib.c
include $(BUILD_SHARED_LIBRARY)
答案 0 :(得分:3)
您的Java包名称似乎名为“com.frank.android.ndk”,您的Java类名称似乎名为“FibLib”,而且与FibN匹配的C函数的名称应为Java_com_frank_android_ndk_FibLib_fibN。这个page由Android文档引用,并详细介绍了C函数的JNI命名约定。
答案 1 :(得分:1)
它只是看起来,或者你的C函数名称在单词ndk之前真的使用双下划线吗?它应该是单下划线恕我直言。
答案 2 :(得分:1)
找不到Lcom/frank/android/ndk/FibLib;.fibN
。日志表明库已成功加载。
该方法应称为Java_com_frank_android_ndk_FibLib_fibN
;在问题中你有一个双下划线,你错过了类名。如果你有两个不同的方法可以解决同一个问题,你可以通过编码参数来区分它们,但这似乎没有必要。
你说这是一个C程序,但有时人们会混淆C和C ++,所以我还要指出,如果这是一个“.cpp”文件,你需要在声明中放入extern "C"
或者C ++将“破坏”函数名称。
另见http://developer.android.com/training/articles/perf-jni.html#faq_ULE
答案 3 :(得分:0)
您是否遵守了使用ndk-build的JNi代码? 类名称应与JNI和Java中描述的相同
Java_com_qualcomm_QCARSamples_VideoPlayback_VideoPlayback_initApplicationNative
initApplicationNative是Java和JNi上应该相同的方法名称 如果没有,那么你会得到这个错误