栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

JNI学习笔记——(一)入门

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JNI学习笔记——(一)入门

注:编码工具是Android Studio。

目录

创建Android Studio编写JNI代码环境

JNI是什么?

javah命令生成native方法签名

案例一:Native修改Java类属性值

案例二:Native调用Java类方法 

Java各种数据类型的签名


创建Android Studio编写JNI代码环境

        File -> New Project -> Native C++。

JNI是什么?

        JNI是JDK提供的一种能够让Java和Native之间互相操作的机制。

javah命令生成native方法签名

        在Java中用native定义本地方法,具体的实现用C/C++实现,Java中可以直接调用native修饰的方法,调用它相当于调用了C/C++实现的方法体。

        JNI有一套固定的native方法签名格式,可以用JDK自带的javah命令生成对应的方法签名。

在MainActivity中定义一个native方法,getStringFromNative,返回值为String,没有形式参数。

package com.wcc.jni.study;

import androidx.appcompat.app.AppCompatActivity;

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

public class MainActivity extends AppCompatActivity {

    // 加载本地库
    static {
        System.loadLibrary("native-lib");
    }

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

        // Example of a call to a native method
        TextView tv = findViewById(R.id.sample_text);
        tv.setText(getStringFromNative());
    }

    // 本地方法在Java中只有声明,没有方法体
    private native String getStringFromNative();
}

在命令行运行javah命令

D:AndroidAndroidStudioProjectsJniStudyappsrcmainjava>javah com.android.jni.study.MainActivity

会在java目录下生成一个.h格式的头文件,里面有native的方法签名。

com_android_jni_study_MainActivity.h

内容

#include 


#ifndef _Included_com_android_jni_study_MainActivity
#define _Included_com_android_jni_study_MainActivity
#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jstring JNICALL Java_com_android_jni_study_MainActivity_getStringFromNative
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

将头文件复制到cpp目录下。

在cpp文件中,引入头文件,并实现方法。

#include 
#include "com_android_jni_study_MainActivity.h"

extern "C" // 必须,所有代码以C形式运行
JNIEXPORT
jstring // 对应Java的String
JNICALL// 可以省略
Java_com_android_jni_study_MainActivity_getStringFromNative
        (JNIEnv *env, // JNI的核心,Java和Native的互相操作都靠env
         jobject jobj// Java中的native方法声明在哪个类,就传哪个类的对象
        ) {
        std::string hi = "hi from native";
        return env->NewStringUTF(hi.c_str());
}

运行结果:

案例一:Native修改Java类属性值

MainActivity代码

package com.android.jni.study;

import androidx.appcompat.app.AppCompatActivity;

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

public class MainActivity extends AppCompatActivity {

    // 加载本地库
    static {
        System.loadLibrary("native-lib");
    }

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

        updateText();
        // Example of a call to a native method
        TextView tv = findViewById(R.id.sample_text);
        tv.setText(text);
    }

    private String text = "default";

    private native void updateText();
}

Native代码

#include 
#include 


extern "C"
JNIEXPORT void JNICALL
Java_com_android_jni_study_MainActivity_updateText(JNIEnv *env, jobject thiz) {
    // 获取jobject对应的jclass
    jclass  jclz = env->GetObjectClass(thiz);
    // 获取Java类属性FieldID
    jfieldID f_id = env->GetFieldID(
            jclz,
            "text",// Java类属性名
            "Ljava/lang/String;"// Java类属性类型签名
            );
    // 创建jstring
    jstring jstr = env->NewStringUTF("NewValue");
    // 通过FieldID修改Java类属性值
    env->SetObjectField(thiz, f_id, jstr);
}

运行结果

案例二:Native调用Java类方法 

MainActivity代码

package com.android.jni.study;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    // 加载本地库
    static {
        System.loadLibrary("native-lib");
    }

    private TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = findViewById(R.id.sample_text);
    }

    public native void callJavaMethod();

    private void print(){
        Log.e("Main", "Call From Native");
    }

    public void click(View view) {
        callJavaMethod();
    }
}

Native代码

#include 
#include 


extern "C"
JNIEXPORT void JNICALL
Java_com_android_jni_study_MainActivity_updateText(JNIEnv *env, jobject thiz) {
    // 获取jobject对应的jclass
    jclass  jclz = env->GetObjectClass(thiz);
    // 获取Java类属性FieldID
    jfieldID f_id = env->GetFieldID(
            jclz,
            "text",// Java类属性名
            "Ljava/lang/String;"// Java类属性类型签名
            );
    // 创建jstring
    jstring jstr = env->NewStringUTF("NewValue");
    // 通过FieldID修改Java类属性值
    env->SetObjectField(thiz, f_id, jstr);
}extern "C"
JNIEXPORT void JNICALL
Java_com_android_jni_study_MainActivity_callJavaMethod(JNIEnv *env, jobject thiz) {
    // 获取jobject的jclass
    jclass jclz = env->GetObjectClass(thiz);
    // 获取methodID
    jmethodID m_id = env->GetMethodID(
            jclz,
            "print",// 方法名
            "()V"// 方法签名
            );
    // 通过methodID调用Java类方法
    env->CallVoidMethod(
            thiz,
            m_id
            );
}

运行结果

Java各种数据类型的签名
boolean --- Z
char --- C
byte --- B
short --- S
int --- I
long --- J
float --- F
double --- D
void --- V
引用类型 --- L全类名; 其中.用/代替,如:String的签名Ljava/lang/String;
数组 --- [元素签名,如:int[]的签名[I

        可以用JDK的javap命令查看某个类中的方法和属性的签名,如:javap -s -p MainActivity,其中MainActivity是Class文件。

        上述命令的输出格式如下:

public class com.android.jni.study.MainActivity extends androidx.appcompat.app.AppCompatActivity {
  private android.widget.TextView tv;
    descriptor: Landroid/widget/TextView;
  public com.android.jni.study.MainActivity();
    descriptor: ()V

  protected void onCreate(android.os.Bundle);
    descriptor: (Landroid/os/Bundle;)V

  public native void callJavaMethod();
    descriptor: ()V

  private void print();
    descriptor: ()V

  public void click(android.view.View);
    descriptor: (Landroid/view/View;)V

  static {};
    descriptor: ()V
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/648756.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号