Как передать указатель значения через API внешней памяти Java

Я хочу вызвать следующий метод в C:

      heif_image_handle* handle;
heif_context_get_primary_image_handle(ctx, &handle);

У меня проблема в том, что у меня нет доступа через C-API к структуре 'heif_image_handle'.

Что я пробовал:

      MemorySegment.allocateNative(C_POINTER).adress()

Может кто-нибудь помочь мне, как я могу использовать этот метод с Panama API. Мой фактический обходной путь состоял в том, чтобы расширить C-API, но первоначальный автор не хочет этого делать.

Мой фактический код находится под: https://github.com/lanthale/LibHeifFX/blob/main/LibHeifFX/src/main/java/org/libheiffx/LibheifImage.java

Заранее спасибо.

1 ответ

Ваш код кажется мне почти правильным. Вам просто нужно удерживать выделенный сегмент (который представляет heif_image_handle**), а затем после вызова heif_context_get_primary_image_handle, извлеките из этого сегмента после того, как библиотека установит в него первичный дескриптор изображения (пример с использованием API JDK 17):

      // allocate blob of memory the size of a pointer
MemorSegment primary_image_handle_seg = MemorySegment.allocateNative(C_POINTER);
// call library to set the handle into the allocated memory
heif_context_get_primary_image_handle(ctx, primary_image_handle_seg.address());
// retrieve pointer from allocated memory
MemoryAddress primary_image_handle = MemoryAccess.getAddress(primary_image_handle_seg);

В общем, выделение стека и получение адреса выделенного значения, как в C, как в показанном фрагменте, невозможно непосредственно в Java. Итак, что касается панамского иностранного API, всякий раз, когда вы видите что-то подобное в коде C:

      some_type* val;

Вам нужно будет выделить для него:

      // some_type** val_ptr;
MemorySegment val_ptr = MemerySegment.allocateNative(C_POINTER, scope);
// some_type** val_ptr_as_ma; (as a bare MemoryAddress)
MemoryAddress val_ptr_as_ma = val.address();
// some_type* val; (dereference/copy val, `*val_ptr`)
MemoryAddress val = MemoryAccess.getAddress(val);

Обратите внимание, что мы должны пройти через MemorySegmentМаршрут в этом случае. Поскольку невозможно получить адрес .

Как правило, в Java API нет эквивалента оператора амперсанда. .address()метод предназначен для преобразования адресоподобных вещей в экземпляры, а не для имитации . И для MemoryAddressсам он просто возвращается this(Так что ваши primary_image_handle.address()вызов не действует).

По сути, эквивалент C того, что мы делаем в Java, без выделения стека и &, это:

      some_type** val_ptr = malloc(sizeof *val_ptr);
func(val_ptr); // void func(some_type** v) { ... }
some_type* val = *val_ptr;
Другие вопросы по тегам