Чтение / запись в память, которая ранее была выделена через JNI - PullRequest
0 голосов
/ 18 октября 2019

Я использую макросы для выделения памяти через JNI, а затем записываю в эту память.

@MacroAllocator
case class SomeCaseClass(a: Int, b: Int, c: Int)

3 * INT.BYTES = 12, поэтому это означает, что мне нужно выделить 12 байтов памяти.

Я написал буфер, в котором хранятся объекты без кучи. и если я уже получаю адрес буфера, я могу использовать этот адрес для записи / чтения.

typedef struct {
    uint8_t *buf;
    size_t   size;
} buf_t;

через jni, я выделяю память (предположим, что это во время компиляции)

JNIEXPORT jlong JNICALL Java_some_package_com_1alloc(JNIEnv *env, jobject self, jint size) {
    globalenv = env;
    buf_t buf;
    buf_alloc(&buf, (size_t) size);

    jlong buf_addr = (jlong)buf.buf;

    return buf_addr;
}

и затем я пытаюсь что-то записать в этот буфер, это тоже нормально (время компиляции тоже)

JNIEXPORT void JNICALL Java_some_package_com_1write_1int(JNIEnv *env, jobject self, jint value, jint idx, jlong buf_addr) {
    globalenv = env;
    uint8_t *buf = (uint8_t*) buf_addr;
    write_int_to_buf_at(buf, idx, value);
    return;
}

и когда все сделано, я пытаюсь прочитать (время выполнения):

JNIEXPORT jint JNICALL Java_some_package_com_read_1int(JNIEnv *env, jobject self, jint idx, jlong buf_addr) {
    globalenv = env;
    uint8_t *buf = (uint8_t*)buf_addr;
    int32_t value = read_int_in_buf_at(buf, (size_t) idx);
    return value;
}

UPD: read_int_in_buf_at func impl

int32_t read_int_in_buf_at(uint8_t *buf, size_t idx) {

    uint8_t b3 = buf[idx + 3];
    uint8_t b2 = buf[idx + 2];
    uint8_t b1 = buf[idx + 1];
    uint8_t b0 = buf[idx];

    return (b3 << 24) | ((b2 & 255) << 16) | 
           ((b1 & 255) << 8) | (b0 & 255);

}

Я получаю странные результаты при попытке прочитать: 0, 1234125360, -1342346458 и т. Д.

1 Ответ

0 голосов
/ 24 октября 2019

Продолжая комментарии, вы должны иметь в виду, что Java_some_package_com_1alloc возвращает адрес выделенной памяти (buf.buf) NOT сама структура buf_t.

Thisозначает, что ваши функции должны измениться соответственно:

JNIEXPORT void JNICALL Java_some_package_com_1write_1int(JNIEnv *env, jobject self, jint value, jint idx, jlong buf_addr) {
    globalenv = env;
    // The `jlong` value is the address of allocated memory 
    uint8_t *buf = (uint8_t*) buf_addr;
    write_int_to_buf_at(buf, idx, value);
}

и читатель:

JNIEXPORT jint JNICALL Java_some_package_com_read_1int(JNIEnv *env, jobject self, jint idx, jlong buf_addr) {
    globalenv = env;
    uint8_t *buf = (uint8_t*) buf_addr;
    int32_t value = read_int_in_buf_at(buf, (size_t) idx);
    return value;
}
...