日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java高级用法之:JNA类型映射应该注意的问题

發(fā)布時間:2024/2/28 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java高级用法之:JNA类型映射应该注意的问题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 簡介
  • String
  • Buffers,Memory,數(shù)組和Pointer
  • 可變參數(shù)
  • 總結

簡介

JNA提供JAVA類型和native類型的映射關系,但是這一種映射關系只是一個大概的映射,我們在實際的應用中還有很多需要注意的事項,本文將會為大家詳細講解在使用類型映射中可能會出現(xiàn)的問題。一起來看看吧。

String

首先是String的映射,JAVA中的String實際上對應的是兩種native類型:const char* 和 const wchar_t*。默認情況下String會被轉(zhuǎn)換成為char* 。

char是ANSI類型的數(shù)據(jù)類型,而wchar_t是Unicode字符的數(shù)據(jù)類型,也叫做寬字符。

如果JAVA的unicode characters要轉(zhuǎn)換成為char數(shù)組,那么需要進行一些編碼操作,如果設置了jna.encoding,那么就會使用設置好的編碼方式來進行編碼。默認情況下編碼方式是 “UTF8”.

如果是WString,那么Unicode values可以直接拷貝到WString中,而不需要進行任何編碼。

先看一個簡單的例子:

char* returnStringArgument(char *arg) {return arg; }wchar_t* returnWStringArgument(wchar_t *arg) {return arg; }

上面的native代碼可以映射為:

String returnStringArgument(String s); WString returnWStringArgument(WString s);

再來看一個不同的例子,假如native方法的定義是這樣的:

int getString(char* buffer, int bufsize);int getUnicodeString(wchar_t* buffer, int bufsize);

我們定義了兩個方法,方法的參數(shù)分別是char* 和wchar_t*。

接下來看一下怎么在JAVA中定義方法的映射:

// Mapping A: int getString(byte[] buf, int bufsize); // Mapping B: int getUnicodeString(char[] buf, int bufsize);

下面是具體的使用:

byte[] buf = new byte[256]; int len = getString(buf, buf.length); String normalCString = Native.toString(buf); String embeddedNULs = new String(buf, 0, len);

可能有同學會問了,既然JAVA中的String可以轉(zhuǎn)換成為char*,為什么這里需要使用byte數(shù)組呢?

這是因為getString方法需要對傳入的char數(shù)組中的內(nèi)容進行修改,但是因為String是不可變的,所以這里是不能直接使用String的,我們需要使用byte數(shù)組。

接著我們使用Native.toString(byte[]) 將byte數(shù)組轉(zhuǎn)換成為JAVA字符串。

再看一個返回值的情況:

// Example A: Returns a C string directly const char* getString(); // Example B: Returns a wide character C string directly const wchar_t* getString();

一般情況下,如果是native方法直接返回string,我們可以使用String進行映射:

// Mapping A String getString(); // Mapping B WString getString();

如果native code為String分配了內(nèi)存空間,那么我們最好使用JNA中的Pointer作為返回值,這樣我們可以在未來某些時候,釋放所占用的空間,如下所示:

Pointer getString();

Buffers,Memory,數(shù)組和Pointer

什么時候需要用到Buffers和Memory呢?

一般情況下如果是基礎數(shù)據(jù)的數(shù)組作為參數(shù)傳到函數(shù)中的話,可以在JAVA中直接使用基礎類的數(shù)組來替代。但是如果native方法在方法返回之后,還需要訪問數(shù)組的話(保存了指向數(shù)組的指針),這種情況下使用基礎類的數(shù)組就不太合適了,這種情況下,我們需要用到ByteBuffers或者Memory。

我們知道JAVA中的數(shù)組是帶有長度的,但是對于native方法來說,返回的數(shù)組實際上是一個指向數(shù)組的指針,我們并不能知道返回數(shù)組的長度,所以如果native方法返回的是數(shù)組指針的話,JAVA代碼中用數(shù)組來進行映射就是不合適的。這種情況下,需要用到Pointer.

Pointer表示的是一個指針,先看一下Pointer的例子,首先是native代碼:

void* returnPointerArgument(void *arg) {return arg; }void* returnPointerArrayElement(void* args[], int which) {return args[which]; }

接下來是JAVA的映射:

Pointer returnPointerArgument(Pointer p);Pointer returnPointerArrayElement(Pointer[] args, int which);

除了基本的Pointer之外,你還可以自定義帶類型的Pointer,也就是PointerType. 只需要繼承PointerType即可,如下所示:

public static class TestPointerType extends PointerType {public TestPointerType() { }public TestPointerType(Pointer p) { super(p); }} TestPointerType returnPointerArrayElement(TestPointerType[] args, int which);

再看一下字符串數(shù)組:

char* returnStringArrayElement(char* args[], int which) {return args[which]; }wchar_t* returnWideStringArrayElement(wchar_t* args[], int which) {return args[which]; }

對應的JAVA映射如下:

String returnStringArrayElement(String[] args, int which);WString returnWideStringArrayElement(WString[] args, int which);

對應Buffer來說,JAVA NIO中提供了很多類型的buffer,比如ByteBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatBuffer和DoubleBuffer等。這里以ByteBuffer為例,來看一下具體的使用.

首先看下native代碼:

int32_t fillInt8Buffer(int8_t *buf, int len, char value) {int i;for (i=0;i < len;i++) {buf[i] = value;}return len; }

這里將buff進行填充,很明顯后續(xù)還需要使用到這個buffer,所以這里使用數(shù)組是不合適的,我們可以選擇使用ByteBuffer:

int fillInt8Buffer(ByteBuffer buf, int len, byte value);

然后看下具體怎么使用:

TestLibrary lib = Native.load("testlib", TestLibrary.class);ByteBuffer buf = ByteBuffer.allocate(1024).order(ByteOrder.nativeOrder());final byte MAGIC = (byte)0xED;lib.fillInt8Buffer(buf, 1024, MAGIC);for (int i=0;i < buf.capacity();i++) {assertEquals("Bad value at index " + i, MAGIC, buf.get(i));}

可變參數(shù)

對于native和JAVA本身來說,都是支持可變參數(shù)的,我們舉個例子,在native方法中:

int32_t addVarArgs(const char *fmt, ...) {va_list ap;int32_t sum = 0;va_start(ap, fmt);while (*fmt) {switch (*fmt++) {case 'd':sum += va_arg(ap, int32_t);break;case 'l':sum += (int) va_arg(ap, int64_t);break;case 's': // short (promoted to 'int' when passed through '...') case 'c': // byte/char (promoted to 'int' when passed through '...')sum += (int) va_arg(ap, int);break;case 'f': // float (promoted to ‘double’ when passed through ‘...’)case 'g': // doublesum += (int) va_arg(ap, double);break;default:break;}}va_end(ap);return sum; }

對應的JAVA方法映射如下:

public int addVarArgs(String fmt, Number... args);

相應的調(diào)用代碼如下:

int arg1 = 1; int arg2 = 2; assertEquals("32-bit integer varargs not added correctly", arg1 + arg2,lib.addVarArgs("dd", arg1, arg2));

總結

本文介紹了在使用JNA方法映射中應該注意的一些細節(jié)和具體的使用問題。

本文的代碼:https://github.com/ddean2009/learn-java-base-9-to-20.git

本文已收錄于 http://www.flydean.com/05-jna-type-mapping-details-md/

最通俗的解讀,最深刻的干貨,最簡潔的教程,眾多你不知道的小技巧等你來發(fā)現(xiàn)!

歡迎關注我的公眾號:「程序那些事」,懂技術,更懂你!

總結

以上是生活随笔為你收集整理的java高级用法之:JNA类型映射应该注意的问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。