介绍JNA提供了JAVA类型和native类型的映射关系,但是这个映射关系只是粗略的映射,我们还有很多需要注意的地方在实际应用中,本文将详细讲解在使用类型映射时可能出现的问题。一起来看看吧。String首先是String的一个映射,而JAVA中的String其实对应了两种原生类型:constchar和constwchar_t。默认情况下,字符串将转换为char*。char是ANSI类型的数据类型,wchar_t是Unicode字符的数据类型,也叫宽字符。如果要将JAVA的unicode字符转换成char数组,需要进行一些编码操作。如果设置了jna.encoding,那么将使用设置的编码方式进行编码。默认情况下,编码方法是“UTF8”。如果是WString,那么Unicode值可以直接复制到WString,不需要任何编码。我们来看一个简单的例子:char*returnStringArgument(char*arg){returnarg;}wchar_t*returnWStringArgument(wchar_t*arg){returnarg;}上面的原生代码可以映射为:StringreturnStringArgument(Strings);WStringreturnWStringArgument(WStrings);让我们看一个不同的例子。如果native方法的定义如下:intgetString(char*buffer,intbufsize);intgetUnicodeString(wchar_t*buffer,intbufsize);我们定义了两个方法,方法参数分别是char和wchar_t。接下来我们看看JAVA中如何定义方法映射://MappingA:intgetString(byte[]buf,intbufsize);//MappingB:intgetUnicodeString(char[]buf,intbufsize);下面是具体的用法:byte[]buf=newbyte[256];intlen=getString(buf,buf.length);字符串normalCString=Native.toString(buf);StringembeddedNULs=newString(buf,0,len);可能有的同学会问,既然JAVA中的String可以转成char*,为什么这里还要用字节数组呢?这是因为getString方法需要修改传入的char数组的内容,但是由于String是不可变的,这里不能直接使用String,我们需要使用byte数组。然后我们使用Native.toString(byte[])将字节数组转换为JAVA字符串。再看另一个返回值://例子A:直接返回一个C字符串constchar*getString();//例子B:直接返回一个宽字符C字符串constwchar_t*getString();一般情况下,如果是直接返回string的native方法,我们可以使用String进行映射://MappingAStringgetString();//映射BWStringgetString();如果native代码为String分配了内存空间,那么我们最好使用JNA中的Pointer作为返回值,这样可以在以后的某个时刻释放占用的空间,如下:PointergetString();Buffers、Memory、arrays和Pointer什么时候需要用到Buffers和Memory?一般如果是基本数据的数组,如果作为参数传递给函数,在JAVA中可以直接换成基类的数组。但是如果native方法在方法返回后需要访问数组(保存数组指针),这种情况下使用基类的数组就不合适了。在这种情况下,我们需要使用ByteBuffers或Memory。我们知道JAVA中的数组是有长度的,但是对于native方法来说,返回的数组实际上是一个指向数组的指针,我们无法知道返回数组的长度,所以如果native方法返回的是数组指针,它在JAVA代码中不宜使用数组进行映射。在这种情况下,您需要使用Pointer。Pointer代表一个指针。让我们看一下Pointer的例子。首先是原生代码:void*returnPointerArgument(void*arg){returnarg;}void*returnPointerArrayElement(void*args[],intwhich){returnargs[which];}接下来是JAVA的映射:Pointerreturn指针参数(指针p);指针返回PointerArrayElement(Pointer[]args,intwhich);除了基本的Pointer,你还可以自定义定义一个Pointer类型,即PointerType。你只需要继承PointerType,如下所示:}}TestPointerTypereturnPointerArrayElement(TestPointerType[]args,intwhich);再看字符串数组:char*returnStringArrayElement(char*args[],intwhich){returnargs[which];}wchar_t*returnWideStringArrayElement(wchar_t*args[],intwhich){returnargs[which];}对应的JAVA映射如下:StringreturnStringArrayElement(String[]args,intwhich);WStringreturnWideStringArrayElement(WString[]args,intwhich);对应Buffer,JAVANIO提供许多类型的缓冲区,如ByteBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer和DoubleBuffer等。这里我们以ByteBuffer为例,看看它是如何使用的。先看原生代码:int32_tfillInt8Buffer(int8_t*buf,intlen,charvalue){inti;对于(i=0;i
