Java中使用JNI调用c/c++的库

一、JNI简介

        在项目开发中,如果需要调用第三方库或者操作系统相关功能,那么在java环境中需要使用到JNI技术。

         从java1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许java代码和其他语言进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。

        当然相比于JNI个人觉得JNA更为简单;什么是JNA可自行百度。

二、JNI的使用示例

话不多说,直接上例子,主要介绍生成.h文件,后续编库使用,参考其他。

1、例子

student类

public class Student {
}

GlApi类

public class GlApi {


    public native int add(int x, int y);
    public native Student del(int name);

}

2、生成.h文件

一、使用javac生成.class文件

javac jnik\GlApi.java

二、使用javah生成.h文件

javah -jni jnik.GlApi

此时生成.h文件

三、错误处理

1、在生成.h文件时,如果出现Exception in thread "main" java.lang.IllegalArgumentException: Not a valid class name: jnik\GlApi,那么是因为使用命令不对,此时使用了javah jnik\GlApi造成上述问题。

解决办法:使用命令如下(注意观察文件.java所在的文件目录,可参考用javah导出类的头文件,Not a valid class name或者错误: 找不到 'HelloNDK' 的类文件_exception in thread "main" java.lang.illegalargume-CSDN博客

javac -jni jnik.GlApi

2、在项目开发中,不得随意移动GlApi的位置,否则会造成java.lang.unsatisfiedLinkerror:GlApi.xxxxxxx(Ljava/lang/Object;)Lentity/RecvEntity;,究其原因,是因为生成.h文件时,在编译库时,位置已经指定。注意观察.h的文件名和其内容

请自行体会,这点本人花费较多时间才发现。

三、补充JNI接口参数为对象时赋值

class recvEntity
{
    String id,
    int taskid,
    int result,
    String data;
    
}
JNIEXPORT jobject JNICALL Java_jni_GlApi_recvfile(JNIEnv *,jobject, jobject);
JNIEXPORT jobject JNICALL Java_jni_GlApi_recvfile(JNIEnv *,jobject, jobject recvEntity)
{
    //获取对象
    jclass JREcvEntity = env->GetObjectClass(recvEntity);
    //获取方法名和名称ID
    jmethodID method_init_id = env->GetMethodID(jREcvEntity, "<init>", "()V");
    
    //从class中获取变量
    jfieldID fperrid = env->GetFieldID(jREcvEntity, "peerid", "[B");
    jfieldID ftaskId = env->GetFieldID(JREcvEntity, "taskid", "I");
    jfieldID fresult = env->GetFieldID(JREcvEntity, "result", "I");
    jfieldID fdata = env->GetFieldID(jREcvEntity, "data", "[B");

    //创建临时对象
    jobject tm_recvEntity = env->NewObject(JREcvEntity, method_init_id);

    unsigned int f_data_len = 0;
    unsigned int f_peerid = 0;
    unsigned int f_taskid = 0;
    unsigned char *file_data = NULL;
    unsigned char ipId[16] = {0};
    int ret = 0;
    
    //调用业务接口
    ret = marketing_trans(ipId, &f_taskid, &file_data, &file_data_len);
    if(ret != 0)
    {
        return NULL;
    }

    //先分配空间
    jbyteArray ipdata = env->NewByteArray(16);
    //赋值
    env->SetByteArrayRegion(ipdata, 0, 16, (const jbyte*)ipId);
    //转化
    char *ipArr = (char *)env->GetByteArrayElements(ipdata, 0);
    env->SetObjectField(tm_recvEntity, fpeerid, env->NewStringUTF(ipArr));
    //释放
    env->DeleteLocalRef(ipdata);

    env->SetIntField(tm_recvEntity, ftaskId, f_taskid);
    env->SetIntField(tm_recvEntity, fresult, f_data_len);

    jbyteArray data = env->NewByteArray(f_data_len);
    env->SetByteArrayRegion(data, 0, f_data_len, (const jbyte*)file_data);
    char *chArr = (char*)env->GetByteArrayElements(data, 0);
    env->SetObjectField(tm_recvEntity, fdata, env->NewStringUTF(chArr));
    //删除局部引用
    env->DeleteLocalRef(data);

    free(file_data);
    file_data = NULL;
    return tm_recvEntity;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值