2012-07-04 16 views
13

Devo passare un (diretto) ByteBuffer alle funzioni native che leggeranno/scrivono da/nel buffer. Una volta completate queste operazioni, desidero accedere allo ByteBuffer dal codice Java utilizzando le normali funzioni; in particolare, limit() e position() dovrebbero riflettere lo stato corrente del buffer.Manipolazione di ByteBuffer da JNI

Da JNI utilizzerà GetDirectBufferAddress() per accedere direttamente buffer sottostante, sto assumendo devo chiamare flip()/limit()/position() dopo che sono fatto lettura/scrittura. Tuttavia, non sono stato in grado di farlo funzionare. Ad esempio, dopo aver letto un paio di byte nel buffer da C e aver impostato il suo limite e la posizione di conseguenza, non posso interrogare quei byte da Java; L'idea di Java del limite e della posizione del buffer non è coerente con ciò che ho fatto nel codice C.

Qualcuno può indicarmi un esempio funzionante di questo? Grazie in anticipo.

+0

Dovrebbe funzionare, questa è l'idea. Quali posizioni e valori limite stai impostando, e come, e quali valori per loro stai vedendo in Java? – EJP

risposta

13

È possibile che il metodo nativo restituisca il numero di byte scritti. Quindi aggiorna ByteBuffer di conseguenza sul lato Java.

public class SomeClass { 
    /** 
    * @param buffer input/output buffer 
    * @return number of bytes written to buffer 
    */ 
    private native int nativeMethod(ByteBuffer buffer); 

    public void myMethod() { 
     ByteBuffer buffer = ByteBuffer.allocateDirect(100); 
     int written = nativeMethod(buffer); 
     if (written > 0) { 
      buffer.limit(written); 
     } 
     ... 
    } 
} 

Modifica

Provare per impostare il valore limite sul lato C sta lavorando troppo, quindi non so perché si hanno problemi con esso.

implementazione Naive (niente cache, ecc):

static jint nativeMethod(JNIEnv *env, jobject obj, jobject buffer) { 
    jclass cls = env->GetObjectClass(buffer); 
    jmethodID mid = env->GetMethodID(cls, "limit", "(I)Ljava/nio/Buffer;"); 
    char *buf = (char*)env->GetDirectBufferAddress(buffer); 
    jlong capacity = env->GetDirectBufferCapacity(buffer); 
    int written = 0; 

    // Do something spectacular with the buffer... 

    env->CallObjectMethod(buffer, mid, written); 
    return written; 
} 

Il limite è impostato sul buffer durante l'ispezione sul lato Java.