JNA множественные пустые указатели внутри C структуры по ссылке - PullRequest
0 голосов
/ 03 февраля 2020

В моем текущем проекте мне нужно реализовать функцию нативных c libs в java проекте. Я использую JNA. И до сих пор достигли хороших результатов. Теперь я застрял в следующей проблеме.

Мне нужно вызвать нативную функцию c:

int retrieveResult(ResultStruct * pResult)

Где структура определена следующим образом:

typedef struct tag_ResultStruct
{
const void *pBuffer;
int sizeX;
int sizeY;
} ResultStruct;

В Java я создал класс, представляющий структуру:

public class ResultStruct extends Structure{
   public Pointer pBuffer;
   public int sizeX;
   public int sizeY;

   @Override
   protected List<String> getFieldOrder(){
      return Arrays.asList(new String[] {"pBuffer", "sizeX", "sizeY"});
   }

   public ResultStruct(){

   }
}

Я вызываю метод Native C с помощью

private interface MyCLib extends Library{
   MyCLib INSTANCE = Native.load("myclib", MyCLib.class);
   int retrieveResult(ResultStruct pResult);
}
ResultStruct resultStruct = new ResultStruct();
resultStruct.pBuffer = new Memory(bufferLen);
int res = MyCLib.INSTANCE.retrieveResult(resultStruct);

Теперь я могу получить ожидаемые значения из sizeX, sizeY и pBuffer с помощью

resultStruct.pBuffer.getByteArray(0, bufferLen);

Теперь я расширяю свою структуру следующим образом:

typedef struct tag_ResultStruct
{
const void* pContext;
const void *pBuffer;
int sizeX;
int sizeY;
} ResultStruct;

И моя Java Структура:

public class ResultStruct extends Structure{
   public Pointer pContext;
   public Pointer pBuffer;
   public int sizeX;
   public int sizeY;

   @Override
   protected List<String> getFieldOrder(){
      return Arrays.asList(new String[] {"pContext", "pBuffer", "sizeX", "sizeY"});
   }

   public ResultStruct(){

   }
}

Проблема в том, что я не хочу использовать pContext. Поэтому я не знаю, какой у него размер, и поэтому не инициализирую указатель. Теперь, когда я пытаюсь извлечь значения из буфера, вызвав:

resultStruct.pBuffer.getByteArray(0, bufferLen);

Я не получаю ожидаемые значения из буфера.

Вопрос

Как поступить с более чем динамическим c полем памяти внутри структуры, переданной по ссылке при использовании JNA? Можно оставить Указатель неинициализированным внутри Структуры?

Я ценю любую помощь. Заранее спасибо.

1 Ответ

0 голосов
/ 07 февраля 2020

Спасибо всем, кто ответил на мой вопрос. Вы поставили меня на правильный путь.

Ответ

Вот ответ на мой вопрос. Возможно, это может помочь кому-то, кто сталкивается с той же или подобной проблемой.

Проблема

В библиотеке, которую я использую (Pylon C API от Basler), упоминается, что вы должны зарегистрироваться один или несколько выходных буферов. Это делается путем выделения буфера и регистрации указателя этого массива.

Обычно я сопоставляю байтовый массив (byte[] buffer = new byte[size]) с буфером uchar * или void *. Это работает, когда буфер заполняется непосредственно в вашей функции c (как в примере, который мне дал Oo.oO).

Но в контексте API, который я использую, указатель получает заполнено чуть позже после того, как оно было зарегистрировано (оно заполняется, когда доступны данные изображения). Я не эксперт, но я думаю, что java массив байтов не работает как настоящий указатель.

Решение

Я изменил распределение буфера в Java на

Pointer pBuffer = new Memory(size)

и сопоставил этот указатель с указателем буфера void * при его регистрации. Теперь указатель буфера работает как положено, и я могу извлечь содержимое буфера позже, используя

byte[] data = pBuffer.getByteArray(0, size)

Это также работает, когда указатель, возвращаемый функцией retrieveResult(...), находится внутри структуры.

...