在Android中使用jni:UNsatisfiedLinkError

use*_*736 6 java-native-interface android header-files unsatisfiedlinkerror

我是jni的新手,我正在修改一个教程来实现一个简单的本机方法,但是我得到了一个不满意的链接错误.据我所知,我完全按照教程中的步骤进行操作.请帮我.

这是java包装器代码:

package com.cookbook.jni;

public class SquaredWrapper {

    // Declare native method (and make it public to expose it directly)
    public static native int squared(int base);

   // Provide additional functionality, that "extends" the native method
   public static int to4(int base)
   {
      int sq = squared(base);
      return squared(sq);
   }

   // Load library
   static {
      System.loadLibrary("squared");
   }
}
Run Code Online (Sandbox Code Playgroud)

这是我的Android.mk文件的样子:

LOCAL_PATH:= $(调用my-dir)

包括$(CLEAR_VARS)

LOCAL_MODULE:=平方LOCAL_SRC_FILES:= squared.c

包含$(BUILD_SHARED_LIBRARY)

这是我的.c文件的样子:

#include "squared.h"
#include <jni.h>

JNIEXPORT jint JNICALL Java_org_edwards_1research_demo_jni_SquaredWrapper_squared
  (JNIEnv * je, jclass jc, jint base)
{
     return (base*base);
}
Run Code Online (Sandbox Code Playgroud)

这是我的.h文件的样子:

enter code here/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_cookbook_jni_SquaredWrapper */

#ifndef _Included_com_cookbook_jni_SquaredWrapper
#define _Included_com_cookbook_jni_SquaredWrapper
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     com_cookbook_jni_SquaredWrapper
* Method:    squared
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_cookbook_jni_SquaredWrapper_squared
  (JNIEnv *, jclass, jint);

#ifdef __cplusplus
}
#endif
#endif
Run Code Online (Sandbox Code Playgroud)

Alc*_*uar 8

您的JNI签名不匹配.在.c文件中,更改:

JNIEXPORT jint JNICALL Java_org_edwards_1research_demo_jni_SquaredWrapper_squared
Run Code Online (Sandbox Code Playgroud)

JNIEXPORT jint JNICALL Java_com_cookbook_jni_SquaredWrapper_squared
Run Code Online (Sandbox Code Playgroud)

通常,有两种方法可以将本机C通过JNI"粘合"到Java函数中.第一个是您在这里尝试做的事情,即使用JNI将识别并与您的相应Java代码相关联的预定签名.第二种是在包含库时将函数指针,签名和Java类名称传递给JNI.

这是将本机函数绑定到适当的Java代码的第二种方法(这将是您的.c文件):

#include "squared.h"
#include <jni.h>

static const char* SquaredWrapper = "com/cookbook/jni/SquaredWrapper";

jint squared(JNIEnv * env, jobject this, jint base) {
     return (base*base);
}

// Methods to register for SquaredWrapper
static JNINativeMethod SquareWrapperMethods[] = {
        {"squared", "(I)I", squared}
};

jint JNI_OnLoad(JavaVM* vm, void* reserved) {
    JNIEnv* env;
    if ( (*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK)
        return JNI_ERR;

    jclass class = (*env)->FindClass(env, SquaredWrapper);
    (*env)->RegisterNatives(env, class, SquaredWrapperMethods, sizeof(SquaredWrapperMethods)/sizeof(SquaredWrapperMethods[0]));

    return JNI_VERSION_1_6;
}

void JNI_OnUnload(JavaVM* vm, void* reserved) {
    JNIEnv* env;
    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
        return;

    jclass class = (*env)->FindClass(env, SquaredWrapper);
    (*env)->UnregisterNatives(env, class);

    return;

}
Run Code Online (Sandbox Code Playgroud)

这是一个很长的时间,但它在绑定本机代码时为您提供了更多的灵活性.平方和包含的定义如您所料.在第4行,static const char*SquaredWrapper是一个转义字符串,其中包含要绑定平方的类的完全限定包名.接近底部的是JNI_OnLoad和JNI_OnUnLoad函数,它们负责绑定和解除库加载和卸载时的函数绑定.最后一块是JNINativeMethod数组.此数组包含每个条目的大小为3的数组,其组件是作为const char*的方法的Java名称,Java方法的JNI签名以及绑定到该方法的本机C函数指针.JNI函数签名告诉环境参数列表格式和Java函数的返回值.格式为"(Arg1Arg2Arg3 ...)Ret",所以一个接受int和double并返回一个float的函数将具有"(ID)F"的签名,并且一个不带参数并返回void的函数将是"()V".我用这个方便的备忘单来记住大部分的简写:

http://dev.kanngard.net/Permalinks/ID_20050509144235.html

祝好运 :)

编辑:哦,顺便说一下,您可能希望将JNI_OnLoad和JNI_UnOnLoad的签名添加到标头中,并更改本机函数原型的名称以反映新的.c文件.