中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java的JNA類型映射注意細節及使用方法

發布時間:2022-04-15 17:31:32 來源:億速云 閱讀:197 作者:zzz 欄目:開發技術

這篇文章主要介紹“Java的JNA類型映射注意細節及使用方法”,在日常操作中,相信很多人在Java的JNA類型映射注意細節及使用方法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java的JNA類型映射注意細節及使用方法”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

String

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

char是ANSI類型的數據類型,而wchar_t是Unicode字符的數據類型,也叫做寬字符。

如果JAVA的unicode characters要轉換成為char數組,那么需要進行一些編碼操作,如果設置了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);

我們定義了兩個方法,方法的參數分別是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可以轉換成為char*,為什么這里需要使用byte數組呢?

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

接著我們使用Native.toString(byte[]) 將byte數組轉換成為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分配了內存空間,那么我們最好使用JNA中的Pointer作為返回值,這樣我們可以在未來某些時候,釋放所占用的空間,如下所示:

Pointer getString();

Buffers,Memory,數組和Pointer

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

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

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

再看一下字符串數組:

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進行填充,很明顯后續還需要使用到這個buffer,所以這里使用數組是不合適的,我們可以選擇使用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));
        }

可變參數

對于native和JAVA本身來說,都是支持可變參數的,我們舉個例子,在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': // double
      sum += (int) va_arg(ap, double);
      break;
    default:
      break;
    }
  }
  va_end(ap);
  return sum;
}

對應的JAVA方法映射如下:

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

相應的調用代碼如下:

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

到此,關于“Java的JNA類型映射注意細節及使用方法”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

班玛县| 洛隆县| 齐齐哈尔市| 台北县| 河西区| 绵阳市| 六枝特区| 进贤县| 全椒县| 彭阳县| 三都| 安远县| 克拉玛依市| 长顺县| 吐鲁番市| 绥芬河市| 即墨市| 梁河县| 聂荣县| 海林市| 长寿区| 白河县| 灵寿县| 克什克腾旗| 安吉县| 灌南县| 仙游县| 滨海县| 顺义区| 山东| 女性| 普兰县| 崇左市| 东安县| 铁力市| 图们市| 南汇区| 滦平县| 增城市| 额济纳旗| 来宾市|