Возврат массива C в Java с использованием JNA
Вопрос
Я не слишком хорошо знаком с C, но мне нужно использовать библиотеку C в моем Java-коде.Я создал DLL и могу получить к ней доступ, но я пытаюсь вернуть массив целых чисел из кода C в код Java.
Я думал, что в C можно просто вернуть указатель на массив, но в моем Java-коде он работает не так, как я ожидал.Вот код C:
int * getConusXY(double latitude, double longitude) {
maparam stcprm;
double reflat = 25, reflon = -95,
lat1 = 20.191999, lon1 = -121.54001,
x1 = 0, y1 = 0, x2 = 1073, y2 = 689,
gsize = 5.079, scaLat = 25, scaLon = -95, orient = 0;
double x, y;
int* xy;
xy = malloc(2 * sizeof *xy);
stlmbr(&stcprm, reflat, reflon);
stcm1p(&stcprm, x1, y1, lat1, lon1, scaLat, scaLon, gsize, orient);
cll2xy(&stcprm, latitude, longitude, &x, &y);
xy[0] = (int) x;
xy[1] = (int) y;
return xy;
}
Если я проверю это на C++, выполнив
int* xy = getConusXY(33.92, -84.33);
cout << xy[0] << " " << xy[1] << endl;
тогда все работает нормально, и я получаю значения 739, 255, как и ожидалось.
Я пытаюсь использовать его в Java с пакетом JNA вот так (но это дает мне 739, -16777214):
public class DmapFDllLibrary {
interface DmapFLibrary extends Library {
DmapFLibrary INSTANCE = (DmapFLibrary) Native.loadLibrary("DmapFDll",
DmapFLibrary.class);
IntByReference getConusXY(double latitude, double longitude);
}
public static void main(String... strings) {
IntByReference xy_ref = DmapFLibrary.INSTANCE.getConusXY(33.92, -84.33);
Pointer p = xy_ref.getPointer();
System.out.println(p.getInt(0) + " " + p.getInt(1));
}
}
В документации JNA говорится о примитивных массивах, таких как int *buf
будет сопоставлен с int[] buf
в Java, но когда я пытаюсь изменить тип возвращаемого значения с IntByReference
к int[]
тогда я получаю нелегальное исключениеArgumentException.
Я не знаю, правильно ли я возвращаю массив из C или просто неправильно получаю к нему доступ в Java.Любая помощь будет оценена по достоинству.
Решение
Я бы не стал использовать такую функцию, потому что возвращаемый массив никогда не будет освобожден/удален.Я бы предпочел изменить функцию C, если смогу:
void myFunc(Pointer resuls, int numBytes, byte const * returnArray)
Другие советы
Код на C хорошо должен быть лучше (см. другие комментарии), однако основная проблема заключается в том, что я неправильно использовал java-метод getInt ()
для указателя , Похоже, мне следовало использовать getIntArray ()
.
Более длинное и, возможно, более четкое объяснение состоит в том, что вы создаете прототип своей Java-функции для получения Pointer (или преемника Pointer) -
byte[] myFunc(Pointer result, int numBytes);
При создании самого обратного вызова вы используете getByteArray (int) или один из других getArrays.
byte[] myFunc(Pointer resuls, int numBytes)
{
return Pointer.getByteArray(numBytes);
}