2009-12-04 58 views
3

我在我的C庫中有一個unsigned char*,我調用一個JNI導出的函數,需要用這個數據設置一個java對象,最好在byte[]JNI/C庫:傳遞字節ptr

但是這個函數會被經常調用,而且它需要複製大量的數據。

是否可以使用ByteBuffer並將該ByteBuffer的指針指定給我的unsigned char*?或者它只是反過來工作?

可我甚至做這沒有拷貝數據?訪問它的最佳方式是什麼?

unsigned char*中的數據大小是已知的。

+0

請給出您的本地方法在Java簽名,以便有人可以找出一個明智的解決方案 – 2009-12-04 18:45:08

+0

@Gregory:它只需要一個對象作爲參數...訪問字段不是問題,分配一個指針或將數據複製到字節[]字段中。 – John 2009-12-04 18:56:14

+0

是什麼問題?這是一個性能問題還是你沒有成功填充數據? – 2009-12-04 19:04:02

回答

4

考慮到您提供的信息很少,這裏有一個可能的解決方案。

對事物的Java端,你會:

package com.stackoverflow; 

public class JNIQuestion 
{ 
    static native void fillByteArray(byte[] buffer); 
} 

而在C面你會:

JNIEXPORT void JNICALL Java_com_stackoverflow_JNIQuestion_fillByteArray(JNIEnv* env, jbyteArray array) 
{ 
    jboolean isCopy; 
    jbyte* buffer = (*env)->GetByteArrayElements(env, array, &isCopy); 
    jsize length = (*env)->GetArrayLength(env, array); 
    jsize i; 

    // do something with the buffer here, replace with something meaningful 
    // PAY ATTENTION TO BUFFER OVERFLOW, DO NOT WRITE BEYOND BUFFER LENGTH 
    for (i = 0; i < length; ++i) 
    buffer[i] = i; 

    // here it is important to use 0 so that JNI takes care of copying 
    // the data back to the Java side in case GetByteArrayElements returned a copy 
    (*env)->ReleaseByteArrayElements(env, buffer, 0); 
} 

使用直接ByteBufferByteBuffer.allocateDirect())也是一個可能的解決方案。但是我只用一個直接ByteBuffer當我需要在緩衝區中的Java端填寫的數據非常精確的偏移。

關於性能,使用byte[]的解決方案應該是令人滿意的,因爲在調用GetByteArrayElements()時,JVM可能會固定字節數組而不是複製它。

一般來說,您會希望儘量減少JNI調用的數量,這意味着從C端訪問對象字段或從C端分配Java將會影響性能。

在任何情況下,輪廓第一,優化下。

PS:我沒有嘗試編譯代碼,可能有錯別字。請參閱JNI GuideJNI Tutorial

+0

此接近,但我怎麼從jobject搶jbyteArray? – John 2009-12-04 19:53:03

+0

你不需要;從Java端執行:'JNIQuestion.fillByteArra(myObject.getByteArray());'從C端訪問對象字段花費更多。 – 2009-12-04 19:57:55

+0

這不是一個選項,我需要從基於事件/隊列的結構中複製我的C庫中的數據......它不像數據總是在那裏。 – John 2009-12-04 20:00:46