Search code examples
javaandroidjava-native-interfacenio

jni NewDirectByteBuffer for java.nio.IntBuffer (NewDirectIntBuffer)


How to make NewDirectByteBuffer for java.nio.IntBuffer? aka how to NewDirectIntBuffer ?

This works ok:

    jclass canvasClass = env->GetObjectClass(obj);
    // in java:      public ByteBuffer command_ids_byte;
    fid_command_id = env->GetFieldID(canvasClass,"command_ids_byte","Ljava/nio/ByteBuffer;");

    jobject new_command_id_buffer = env->NewDirectByteBuffer(command_id.data(), command_id.size()*sizeof(int));
    env->SetObjectField(obj, fid_command_id, new_command_id_buffer);

While this does not (app just crashes):

    jclass canvasClass = env->GetObjectClass(obj);
    // in java:      public IntBuffer command_ids;
    fid_command_id = env->GetFieldID(canvasClass,"command_ids","Ljava/nio/IntBuffer;");

    // I'd want to have NewDirectIntBuffer here
    jobject new_command_id_buffer = env->NewDirectByteBuffer(command_id.data(), command_id.size()*sizeof(int));
    env->SetObjectField(obj, fid_command_id, new_command_id_buffer);

Solution

  • std::vector<jfloat> rect_x1;
    
    // call with endian = ByteOrder.nativeOrder() from Java    
    void flush(JNIEnv* env, jobject obj, jobject endian){
      jclass canvasClass = env->GetObjectClass(obj);
    
      jclass ByteBufferClass = env->FindClass("java/nio/ByteBuffer");
      jclass FloatBufferClass = env->FindClass("java/nio/FloatBuffer");
      jmethodID asFloatBuffer_methodID = env->GetMethodID(ByteBufferClass, "asFloatBuffer", "()Ljava/nio/FloatBuffer;");
    
      jmethodID order_methodID = env->GetMethodID(ByteBufferClass, "order", "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
    
          {
              jfieldID fid = env->GetFieldID(canvasClass, "drawRect_x1",
                                             "Ljava/nio/FloatBuffer;");
              jobject new_buffer = env->NewDirectByteBuffer(rect_x1.data(),
                                                            rect_x1.size() * sizeof(jfloat));
              env->CallObjectMethod(new_buffer, order_methodID, endian);
              jobject new_buffer_float = env->CallObjectMethod(new_buffer,
                                                               asFloatBuffer_methodID);
              env->SetObjectField(obj, fid, new_buffer_float);
            }
    }