7

私は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");
   }
}

Android.mkファイルは次のようになります。

LOCAL_PATH:= $(my-dirを呼び出す)

$(CLEAR_VARS)を含める

LOCAL_MODULE:=平方LOCAL_SRC_FILES:=平方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);
}

そして、これが私の.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
4

2 に答える 2

8

JNI署名が一致しません。.cファイルで、次を変更します。

JNIEXPORT jint JNICALL Java_org_edwards_1research_demo_jni_SquaredWrapper_squared

JNIEXPORT jint JNICALL Java_com_cookbook_jni_SquaredWrapper_squared

一般に、JNIを介してネイティブCをJava関数に「接着」する方法は2つあります。1つ目は、ここで実行しようとしていることです。つまり、JNIが認識し、適切なJavaコードに関連付ける事前定義された署名を使用します。2つ目は、ライブラリを含めるときに、関数ポインタ、シグニチャ、およびJavaクラス名をJNIに渡すことです。

ネイティブ関数を適切なJavaコード(これは.cファイルになります)にバインドする2番目の方法は次のとおりです。

#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;

}

かなり長くなりますが、ネイティブコードをバインドする際の柔軟性が大幅に向上します。二乗とインクルードの定義は、予想どおりです。4行目では、static const char * SquaredWrapperは、二乗してバインドするクラスの完全修飾パッケージ名を持つエスケープされた文字列です。下部の近くには、ライブラリのロードとアンロードで関数のバインドとバインド解除を処理するJNI_OnLoad関数とJNI_OnUnLoad関数があります。最後の部分はJNINativeMethod配列です。この配列には、各エントリとしてサイズ3の配列が含まれ、そのコンポーネントは、const char *としてのメソッドのJava名、JavaメソッドのJNI署名、およびそのメソッドにバインドするためのネイティブC関数ポインターです。JNI関数のシグネチャは、Java関数の引数リストの形式と戻り値を環境に通知します。形式は「

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

幸運を :)

編集:ああ、ところで、JNI_OnLoadとJNI_UnOnLoadの署名をヘッダーに追加し、新しい.cファイルを反映するようにネイティブ関数プロトタイプの名前を変更することをお勧めします。

于 2012-07-24T13:55:54.423 に答える
0

これは一種のあいまいなケースですが、ネイティブコードでアクセス違反が発生した場合、Androidはスローされた例外を隠蔽し、発生したエラーをスローします。私の場合、ネイティブコードはアクセス違反をスローしましたが、Javaは実行を続けました。次に、クラッシュしたNDKでJNIメソッドを呼び出そうとしました。

アクセス違反を見つけるために、問題のあるJNIメソッドを別のIDEに移動してデバッグすることになりました。

これにより、誰かがこれを理解するのにかかった時間を節約できることを願っています。

于 2020-07-21T13:52:20.300 に答える