jni新手笔记二:java调用c++

96
DON_1007
2019.03.21 14:13* 字数 533

jni作为 java代码与c/c++ 代码之间的桥梁,通过jni可以实现java代码和c/c++代码互相调用

jni新手笔记一 中已经可以通过ndk编译生成libhello.so文件
其中hello.h文件中定义了一个简单的方法 getHello(),这里简单演示下如何通过jni实现java代码调用c++代码

一、新建native方法

java代码调用c/c++代码需要通过native方法,创建native方法之后,使用native方法所在类生成jni头文件,java代码调用native方法将会通过jni调用实现这个头文件的c/c++源文件,通过这种方式就实现了java代码调用c/c++代码
新建类文件NDKTest.java,在类文件中声明native方法getHello()

image.png

生成jni头文件需要中间文件NDKTest.class,所以运行Build->Make Project,在build目录下找到NDKTest.class 文件,不同版本的Android Studio 生成的.class文件的路径不一样,但都会在build目录下

image.png

terminal中进入classes目录下,通过javah -jni 命令生成jni头文件
image.png

运行 javah -jni com.don.ndk.NDKTest,成功之后会得到头文件 com_don_ndk_NDKTest.h

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

#ifndef _Included_com_don_ndk_NDKTest
#define _Included_com_don_ndk_NDKTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_don_ndk_NDKTest
 * Method:    getHello
 * Signature: (I)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_don_ndk_NDKTest_getHello
  (JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif

生成的方法名为Java_com_don_ndk_NDKTest_getHello,但是参数有 3 个,分别是 JNIEnv,jobject,jint,这其中第三个参数jint对应着java代码中 getHello 函数的参数(int count);前两个值是固定的,JNIEnv表示java环境,这个值很重要,可以说我们在jni的实现离不了它;jobject 表示当前的调用对象,在这里就是NDKTest的一个实例

二、调用c++代码

将第一步生成的头文件com_don_ndk_NDKTest.h放到ndk目录下并新建ndktest.cpp实现该头文件

image.png

ndktest.cpp调用hello.h中的getHello()方法

需要强调一点的是,在调用native方法之前需要保证对应的so加载成功,在上一篇中配置的so库名字为hello,在javaNDKTest中加载so hello

package com.don.ndk;

public class NDKTest {

    static {
        System.loadLibrary("hello");
    }

    public native String getHello(int count);

}

MainActivity中调用 getHello方法

package com.don.ndk;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView mTextView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextView = findViewById(R.id.text);
        NDKTest ndkTest = new NDKTest();
        mTextView.setText(ndkTest.getHello(6));
    }
}

编译运行app,可以看到屏幕上显示 hello

Android