Android - NDK:调用Jni方法并传入 int, double, float, String类型的参数

调用Jni方法并传入 int, double, float, String类型的参数

本文介绍java层向jni层传递基本数据类型的参数,主要涉及到java层–>jni层–>c/c++层的数据转换,模拟了从java层到jni层再到C/C++层的调用流程。

1、java层声明native方法

    /**
     * 两个数相加,然后把结果转换成String再返回来
     * @param a
     * @param b
     * @return
     */
    public native String setIntParam(int a,int b);

    /**
     * 返回结果字符串
     * @param d1
     * @param d2
     * @return
     */
    public native String setDoubleParam(double d1,double d2);

    /**
     * 返回结果字符串
     * @param f1
     * @param f2
     * @return
     */
    public native String setFloatParam(float f1,float f2);
    
    /**
     * 在jni中把接收到的参数前面加上一个字符串再返回来
     * @param stringParam
     * @return
     */
    public native String setStringParam(String stringParam);

2、在MainActivity中调用

// int类型相加
binding.btnSetInt.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Toast.makeText(MainActivity.this,setIntParam(4,5),Toast.LENGTH_SHORT).show();
    }
});

// double类型相加
binding.btn2Double.setOnClickListener(view->{
    double a = 4.21d;
    double b = 5.12;
    Toast.makeText(MainActivity.this,setDoubleParam(a,b),Toast.LENGTH_SHORT).show();
});

// double类型相加
binding.btnAddFloat.setOnClickListener(view->{
    float f1 = 2.3f;
    float f2 = 4.5f;
    String floatRet = setFloatParam(f1,f2);
    String finalRet = f1 + " + " + f2 + " = " + floatRet;
    Toast.makeText(MainActivity.this,finalRet,Toast.LENGTH_SHORT).show();
});

// 在jni中把接收到的参数前面加上一个字符串再返回来
binding.btnSetStringParam.setOnClickListener(view->{
    String strParam = "java to c -> setParam";
    String strRet = setStringParam(strParam);
    Toast.makeText(this, strRet, Toast.LENGTH_SHORT).show();
});

3、C++层文件的定义(MyTask.h / MyTask.cpp)

//
// MyTask.h
// Created by lixm on 2024/9/4.
//
#ifndef NDKTEST_MYTASK_H
#define NDKTEST_MYTASK_H

int addInt(int a,int b);

double addDouble(double a,double b);

float addFloat(float a,float b);

#endif //NDKTEST_MYTASK_H
//
// MyTask.cpp
// Created by lixm on 2024/9/4.
//
#include <iostream>
using namespace std;

int addInt(int a,int b){
    cout << "in addInt() a = " << a << ", b = " << b << endl;
    return a + b;
}

double addDouble(double a,double b){
    cout << "in addDouble() a = " << a << ", b = " << b << endl;
    return a + b;
}

float addFloat(float a,float b){
    cout << "in addFloat() a = " << a << ", b = " << b << endl;
    return a + b;
}

4、jni层文件的定义

#include <jni.h>
#include <string>
#include "MyTask.h"
#include <iostream>

#include <android/log.h>

#define LOG_TAG "MyJNILog"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG ,__VA_ARGS__) // 定义LOGI类型
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG ,__VA_ARGS__) // 定义LOGD类型
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG ,__VA_ARGS__) // 定义LOGW类型
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG ,__VA_ARGS__) // 定义LOGE类型
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG ,__VA_ARGS__) // 定义LOGF类型


extern "C"
JNIEXPORT jstring JNICALL
Java_com_hisign_ndktest_MainActivity_setIntParam(JNIEnv *env, jobject thiz, jint a, jint b) {
    // todo 这里模拟了数字转字符串,和字符串的拼接返回
    // int 和 jint可以直接互转
    int sum = addInt(a, b);
    char buf[100];
    sprintf(buf, "%d", sum);    // 数组转字符串
    LOGI("strPre = %s", buf);
    // 直接返回计算结果的字符串
    //return (*env).NewStringUTF(buf);

    char *strPre = "result is : ";  // 使用字符串字面量(不能被改变)
    char tmp[50];  // 定义一个临时的缓冲区
    strcpy(tmp, strPre); // 把字符串值拷贝到缓冲区里面
    strcat(tmp, buf);   //  连接两个字符串
    //C字符串转java字符串
    return (*env).NewStringUTF(tmp);
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_hisign_ndktest_MainActivity_setDoubleParam(JNIEnv *env, jobject thiz, jdouble a,jdouble b) {
    // todo 注意这里的format用%f
    LOGI("ina native , a = %f,b= %f", a, b);
    double sum = addDouble(a, b);
    LOGI("ina native , sum = %f", sum);
    char buf[100];
    sprintf(buf, "%f", sum);   // todo 注意这里的format用%f
    LOGI("strPre = %s", buf);
    // 直接返回计算结果的字符串
    return (*env).NewStringUTF(buf);
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_hisign_ndktest_MainActivity_setFloatParam(JNIEnv *env, jobject thiz, jfloat f1,jfloat f2) {
    LOGI("x = %f, y= %f", f1, f2);
    float sum = addFloat(f1, f2);
    char buf[100];
    sprintf(buf, "%f", sum);  // float类型的结果转换为C字符串,format用%f
    LOGI("addFloat(),result = %s", buf);
    // 直接返回计算结果的字符串
    return (*env).NewStringUTF(buf);
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_hisign_ndktest_MainActivity_setStringParam(JNIEnv *env, jobject thiz,
                                                    jstring string_param) {
    // 创建一个C字符串
    char *strPre = "you input param is : ";
    
    // 把java的字符串转换为c的字符串
    const char *c_str = env->GetStringUTFChars(string_param, NULL);
    LOGI("c_str = %s", c_str);
  
    // 把两个C字符串连接在一起
    int len1 = strlen(strPre);
    int len2 = strlen(c_str);
    LOGI("len1 = %d, len2 = %d", len1, len2);

    char buf[len1 + len2 + 4];
    memset(buf, 0, sizeof(buf));
    strcpy(buf, strPre);
    strcat(buf, c_str);
    printf("result = %s", buf);
    LOGI("result = %s", buf);
    return (*env).NewStringUTF(buf);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值