您的位置 首页 java

想了解JNI与C++的关联吗

背景

在很多时候 Java 调用动态库文件使用JNA是比 jni 体验更好,但有时候你会发现JNA也一样会出现错误的调用结果,这个时候我们需要C++底层语言去做调用动态库文件,其好处是非常高效且准确。但是C++语言怎么与java互通使其能通过java的语言调用C++里写的方法呢?

方法

答案是JNI,JNI是Java Native Interface的缩写,是java本地接口直通底层语言的纽带,他可以与C++完美的结合,下面让我们来看下如何结合。

步骤

我们把整个方法过程分如下步骤

  • 首先编写java类,类名为DoorCardBt55Jni。注意 package ,这个package会决定你接下来java调用你后面采用C++生成对应的.dll文件的调用,如果换包将会调用不成功。

  • 编译上步骤里的类文件,使其生成. class文件
  • 通过javah指令生成C++的 头文件

  • 通过上面的javac,javah指令可在对应的目录下生成如下C++头文件

  • 我们可以大致看下这个头文件

  • 然后将这个.h头文件加入到C++的开发工具中进行开发。新建一个BTFiveJava的C++的DLL项目,将头文件加入,并新建与生成的头文件同名的 源文件 .cpp。其中jni.h,jni_md.h是需要到java的jre的相关目录中获取。

  • 开始开发源文件.cpp,这里主要是看从java到C++类型的过度,可以看到在最初声明java的方法XMS_Read_Guest_Card的时候是3个参数分别是int,String,String,生成头文件后变成jint,jstring,jstring,C++中的jint与java的int是一致的。定义的方法返回值是String[]数组,在C++中变成,jobjectArray,也是数组的意思。

  • 通过编写代码生成BTFiveJava.dll文件

  • 再回到java中,使用JNI方法来调用BTFiveJava.dll文件

知识点

上面步骤中最关键的知识点是.h文件中参数的传递和返回,我们来看下这个方法

JNIEXPORT jobjectArray JNICALL Java_com_foxhis_itf_doorcard_btff_DoorCardBt55Jni_XMS_1Read_1Guest_1Card

(JNIEnv * env, jobject obj, jint port, jstring hotelid, jstring hotelpwd)

JNIEXPORT :关键字,代表此修饰的方法为生成DLL的方法名

jobectArray:数组返回值,代表对应java的数组Strng[]

JNICALL:关键字,JNI调用触发

Java_com_foxhis_itf_doorcard_btff_DoorCardBt55Jni_XMS_1Read_1Guest_1Card:Java_java声明native方法的全名(.换成_)

JNIEnv * :代表java的JVM参数,可调用其中换算类型方法

jobject :代表当前java调用该方法的类,如上例子中的Test。

jint port, jstring hotelid, jstring hotelpwd:上面步骤中有介绍。

jstring 与 字符串 数组返回

在Java中,使用的字符串String对象是Unicoode(UTF-16)码,即每个字符不论是中文还是英文还是符号,一个字符总是占用两个字节。

但是在C/C++中一个字符是一个字节,但是C/C++中的宽字符是两个字节的。Java通过JNI接口可以将Java的字符串转换到C/C++的宽字符串(wchar_t*),或是传回一个UTF-8的字符串(char*)到C/C++,反过来,C/C++可以通过一个宽字符串,或是一个UTF-8编码的字符串创建一个Java端的String对象。

如:

const char* hID = env->GetStringUTFChars(hotelid, NULL);

const char* hPWD = env->GetStringUTFChars(hotelpwd,NULL);

通过GetStringUTFChars方法可将jstring(java中的string类型)转成C/C++中可用的字符串类型const char*(LPCSTR)。

而jint其实对应C++的是long类型,因为java中int始终是4个字节32位。而C/C++是根据操作系统来决定int类型的位数。

我们看看jni.h和jni_md.h头文件,可以更直观的了解:

typedef unsigned char jboolean;

typedef unsigned short jchar;

typedef short jshort;

typedef float jfloat;

typedef double jdouble;

typedef long jint;

typedef __int64 jlong;

typedef signed char jbyte;

最后介绍下如何创建字符串数组,NewObjectArray就是生成一个对象数组,它有三个参数,分别代表,数组长度,类型,初始化。

jobjectArray ret = env->NewObjectArray(jsize,env->FindClass(“Ljava/lang/String;”),NULL);通过这个方法创建jsize大小的对象空值数组。再通过循环遍历数组,再调用env->SetObjectArrayElement(ret, i, env->NewStringUTF(args[i].c_str()))将其值传入ret数组。

实现生成对应java的String[]数组。

如该篇文章对您有帮助记得收藏+转发,想学习更多知识记得关注哦,有疑问可下方留言,谢谢!

文章来源:智云一二三科技

文章标题:想了解JNI与C++的关联吗

文章地址:https://www.zhihuclub.com/188232.shtml

关于作者: 智云科技

热门文章

网站地图