Возврат массива C в Java с использованием JNA - PullRequest
7 голосов
/ 16 сентября 2009

Я не слишком знаком с C, но мне нужно использовать библиотеку C в моем коде Java. Я создал DLL и могу получить к ней доступ, но я пытаюсь вернуть массив целых чисел из кода C в код Java.

В Си я думал, что вы можете просто вернуть указатель на массив, но он не работает так, как я ожидаю в моем коде 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[], тогда я получаю недопустимое исключениеArgmentException. *

Я не знаю, правильно ли я возвращаю массив из C или просто неправильно обращаюсь к нему в Java. Любая помощь будет оценена.

Ответы [ 3 ]

6 голосов
/ 16 сентября 2009

Код C в порядке должен быть лучше (см. Другие комментарии), однако основная проблема заключается в том, что я неправильно использовал метод java getInt() для указателя. Кажется, я должен был использовать getIntArray().

4 голосов
/ 02 ноября 2011

Я бы не использовал такую ​​функцию, потому что возвращенный массив никогда не будет освобожден / удален. Я бы предпочел изменить функцию C, если смогу:

void myFunc(Pointer resuls, int numBytes, byte const * returnArray)

3 голосов
/ 28 октября 2010

Более длинное и, возможно, более четкое объяснение состоит в том, что вы создаете прототип своей функции Java для получения Pointer (или преемника Pointer) -

byte[] myFunc(Pointer result, int numBytes);

При создании самого обратного вызова вы используете getByteArray (int) или один из других getArrays.

byte[] myFunc(Pointer resuls, int numBytes)
{
     return Pointer.getByteArray(numBytes);
}
...