2

我正在尝试运行并理解这个例子: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)
4

4 回答 4

3

您的 Java 包名称似乎命名为“com.frank.android.ndk”,您的 Java 类名称似乎命名为“FibLib”,而与 FibN 匹配的 C 函数的名称应为 Java_com_frank_android_ndk_FibLib_fibN。此页面由 Android 文档引用,并详细介绍了 C 函数的 JNI 命名约定。

于 2012-12-23T03:13:35.643 回答
1

它只是看起来,还是你的 C 函数名称真的在单词 ndk 之前使用双下划线?它应该是单下划线恕我直言。

于 2012-12-21T18:27:30.067 回答
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

于 2012-12-21T23:07:56.610 回答
0

您是否使用 ndk-build 遵守了 JNi 代码?类名应与 JNI 和 Java 中的描述相同

Java_com_qualcomm_QCARSamples_VideoPlayback_VideoPlayback_initApplicationNative

initApplicationNative 是在 Java 和 JNi 上应该相同的方法名称,如果不是,那么您将收到此错误

于 2012-12-21T10:50:11.183 回答