简单 JNI实现java与C++集成

1. 使用环境Android Studio
在这里插入图片描述
注1:language 选择java(另一个选择kotlin 语法完全不熟);
注2:SDK根据你的实际安卓设备选择;

2. 配置gradle(默认gradle 地址下载速度慢)
2.1)gradle-wrapper.properties;
–替换distributionUrl:https://mirrors.cloud.tencent.com/gradle/gradle-8.0-bin.zip
2.2)选择配置文件setting.gradle
–插件pluginManagement仓库添加下载路径
maven { url ‘https://maven.aliyun.com/repository/gradle-plugin’ }
maven { url ‘https://maven.aliyun.com/repository/google’ }

3. 工程结构
在这里插入图片描述
3.1 java端是MainActivity.java 需要调用接口;
3.2 cpp端是native-lib.cpp 实现接口。

4. java端代码

package com.example.helloworld;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import android.util.Log;
import java.util.logging.*;
import com.example.helloworld.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "RenSichao";
    Logger logger = Logger.getLogger("Rensichao");
    // Used to load the 'helloworld' library on application startup.
    static {
        System.loadLibrary("helloworld");
    }

    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        // Example of a call to a native method
        TextView tv = binding.sampleText;
        tv.setText(stringFromJNI());

        boolean flag = boolfromJNI();
        logger.log(Level.INFO, String.format("boolfromJNI return %b",flag));

        byte[] array={1,2,3,4,5};
        byte[] recv = arrayfromJNI(array);
        for(int i=0;i<5;i++)
        {
            logger.log(Level.INFO, String.format("arr return %d",array[i]));
        }
    }
    /**
     * A native method that is implemented by the 'helloworld' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();
    public native boolean boolfromJNI();
    public native byte[] arrayfromJNI(byte[] arr);
}

注:其实就3个接口,在OnCreate中调用

public native String stringFromJNI();  //工程自带
public native boolean boolfromJNI();
public native byte[] arrayfromJNI(byte[] arr);

5. cpp端代码

#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_helloworld_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

extern "C" JNIEXPORT jboolean JNICALL
        Java_com_example_helloworld_MainActivity_boolfromJNI(
                JNIEnv* env,
                jobject /* this */) {
    bool flag = true;
    return flag;
}

extern "C" JNIEXPORT jbyteArray JNICALL
Java_com_example_helloworld_MainActivity_arrayfromJNI(
        JNIEnv* env,
        jobject /* this */,jbyteArray arr)
{
    jbyte *add = env->GetByteArrayElements(arr, nullptr);
    for(int i=0;i<5;i++)
    {
        add[i]=add[i]+1;
    }
    env->SetByteArrayRegion(arr,0,5,(jbyte*)add);
    env->ReleaseByteArrayElements(arr, add, 0);
    return arr;
}

注1:可以看到java调用c++的接口,是通过jni实现的。有特定的函数名:

extern "C" JNIEXPORT xxx Java_com_example_helloworld_MainActivity_xxx()

注2:传递的参数都是jni中的类型。

6. 调试中遇到的问题:
6.1)实现格式化参数打印log;
无论使用Log.i()还是Logger对象,打印对象都是string字符串,没有像C/C++直接设置格式化参数方式。需要通过Sting.format(“hello world %d”,i)的方法转成字符串,间接有log接口输出。
具体的格式说明参考:https://blog.csdn.net/anita9999/article/details/82346552

6.2)构造数组需要选用byte[]而不是Byte[],后者是类不是java的基础类型;

6.3)C++接口实现有输入参数,处理时需要调用env->Getxxx,不能直接处理;

6.4)通常env->Getxxx 与 env->Releasexxx 一起使用释放资源。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值