關於JNI的使用總結

  今天剛整了一下JNI,在百度上看了好多博客,好像在遇到問題方面解釋的都比較少,安卓應用程序使用ndk開發的時候就使用了JNI,而且cocos2d-x移植到安卓平臺的時候也有JNI的使用。

  廢話不多說,貼代碼,對了,這個例子是在別的博客上看到了,但是他沒有解釋錯誤的方面

public class Sample1 {
    public native int intMethod(int n);
    public native boolean booleanMethod(boolean bool);//因爲這個都是沒有實現的,所以加上native,感覺跟c++裏面方法的聲名類似
    public native String stringMethod(String text);
    public native int intArrayMethod(int[] intArray);
   
    public static void main(String[] args) {
        System.loadLibrary("Sample1");//這個函數用來加載在windows平臺的Sample1.dll,就是接下來就說的生成的動態鏈接庫
        Sample1 sample = new Sample1();
        int square = sample.intMethod(5);
        boolean bool = sample.booleanMethod(true);
        String text = sample.stringMethod("Java");
        int sum = sample.intArrayMethod(new int[]{1,2,3,4,5,8,13});
         
        System.out.println("intMethod: " + square);
        System.out.println("booleanMethod: " + bool);
        System.out.println("stringMethod: " + text);
        System.out.println("intArrayMethod: " + sum);
    }
}

然後javac得到.class文件,接着用javah -classpath . Sample1得到Sample1.h頭文件 -classpath 是指定文件所在目錄,一個點就代表當前目錄,貼出Sample1.h

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

#ifndef _Included_Sample1
#define _Included_Sample1
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Sample1
 * Method:    intMethod
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_Sample1_intMethod
  (JNIEnv *, jobject, jint);

/*
 * Class:     Sample1
 * Method:    booleanMethod
 * Signature: (Z)Z
 */
JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod
  (JNIEnv *, jobject, jboolean);

/*
 * Class:     Sample1
 * Method:    stringMethod
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_Sample1_stringMethod
  (JNIEnv *, jobject, jstring);

/*
 * Class:     Sample1
 * Method:    intArrayMethod
 * Signature: ([I)I
 */
JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod
  (JNIEnv *, jobject, jintArray);

#ifdef __cplusplus
}
#endif
#endif

然後貼出實現的代碼

#include "Sample1.h"
#include <string>
#include <string.h>
#include <algorithm>
 
JNIEXPORT jint JNICALL Java_Sample1_intMethod
  (JNIEnv *env, jobject obj, jint num)
{
    return num * num;
}
 
JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod
  (JNIEnv *env, jobject obj, jboolean boolean)
{
    return !boolean;
}
 
JNIEXPORT jstring JNICALL Java_Sample1_stringMethod
  (JNIEnv *env, jobject obj, jstring string)
{
    const char* str = env->GetStringUTFChars(string, 0);
    char cap[128];
	strcpy_s(cap, str);
    env->ReleaseStringUTFChars(string, 0);
	std::string strs(cap);
	std::transform(strs.begin(), strs.end(), strs.begin(), toupper);
    return env->NewStringUTF(strs.c_str());
}
 
JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod
  (JNIEnv *env, jobject obj, jintArray array)
{
    int i, sum = 0;
    jsize len = env->GetArrayLength(array);
    jint *body = env->GetIntArrayElements(array, 0);
     
    for (i = 0; i < len; ++i)
    {
        sum += body[i];
    }
    env->ReleaseIntArrayElements(array, body, 0);
    return sum;
}

這裏的env使用的方法是固定的,JNIEnv提供了很多在java和c++之間數據轉換的方法

這裏我使用vs2013生成動態鏈接庫,生成動態鏈接庫的時候要注意,如果使用的是64位的機子,那可能會報Can't load IA 32-bit .dll on a AMD 64-bit platform這個錯誤,原因就是字面上的意思,怎麼生成64位的庫呢

生成-->配置管理器-->活動平臺解決方案。把從此處複製選擇爲x64,然後把平臺選擇爲x64,然後重新生成就可以生成64位的動態鏈接庫了

還有一個比較坑爹的錯誤找不到或無法加載主類 Sample1,這個出現的原因好像是classpath最後少了一個分號,也許你認爲你的classpath是正確的,但是真的就是缺少了最後面一個分號;

最後成功了之後就會正常輸出了


發佈了23 篇原創文章 · 獲贊 9 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章