Как передать указатель значения через 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;