使用JNI進行Java與C/C++語言混合編程

  • Sample1.java
public class Sample1
{
    public native int intMethod(int n);
    public native boolean booleanMethod(boolean bool);
    public native String stringMethod(String text);
    public native int intArrayMethod(int[] intArray);

    public static void main(String[] args)
    {
        System.loadLibrary("Sample1");
        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);
    }
}

編譯 Sample1.java

javac Sample1.java

產生 header file Sample1.h

javah -jni  Sample1
/* 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

  • Sample1.c
#include "Sample1.h"
#include <ctype.h>
#include <string.h>

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(env, string, 0);
    char cap[128];
    int i;

    strcpy(cap, str);
    (*env)->ReleaseStringUTFChars(env, string, 0);

    for (i = 0; i < sizeof(cap); i++) {
        cap[i] = tolower(cap[i]);
    }

    return (*env)->NewStringUTF(env, cap);
}

JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod
(JNIEnv* env, jobject obj, jintArray array)
{
    int i, sum = 0;
    jsize len = (*env)->GetArrayLength(env, array);
    jint* body = (*env)->GetIntArrayElements(env, array, 0);

    for (i = 0; i < len; ++i) {
        sum += body[i];
    }

    (*env)->ReleaseIntArrayElements(env, array, body, 0);
    return sum;
}

編譯成SO for Linux

gcc -fPIC -Wall -I /usr/lib/jvm/java-8-openjdk-amd64/include/ -I /usr/lib/jvm/java-8-openjdk-amd64/include/linux/ -shared -o libSample1.so Sample1.c

Run

java -Djava.library.path=. Sample1
intMethod: 25
booleanMethod: false
stringMethod: java
intArrayMethod: 36

书籍推荐