Первая структура возвращаемого массива пуста - PullRequest
0 голосов
/ 13 марта 2012

Я пытаюсь создать библиотеку C ++, которую можно использовать из Java через JNA. Я делаю несколько тестов, чтобы вернуть массив структур. Я создал следующую структуру:

C ++:

namespace structures
{
    typedef struct _Point {
        int x, y;
    } Point;
}

Java:

public class Point extends Structure {
    public Point() {
    // required for toArray()
    }

    public Point(Pointer pointer) {
    super(pointer);
    }

    public int x, y;
}

Итак, у меня есть метод C ++, который возвращает массив точек:

extern "C" __declspec(dllexport) structures::Point* getPoints(){
    structures::Point *p;
    p = (structures::Point *) malloc( 4 * sizeof(structures::Point) );
    p[0].x = 10;
    p[0].y = 20;
    p[1].x = 30;
    p[1].y = 40;
    p[2].x = 50;
    p[2].y = 60;
    p[3].x = 70;
    p[3].y = 80;
    return p ;

А в Java это интерфейс, который объявляет доступ к библиотеке:

public interface Multiplyt extends Library{
    Pointer getPoints();
}

А вот код, который тестирует библиотеку:

Pointer pointer = test.getPoints();
Point point, points[];
point = new Point(pointer);
points = (Point[]) point.toArray(4);
System.out.println("0x:"+points[0].x + " 0y:" + points[0].y + " 1x:"+ points[1].x + " 1y:" + points[1].y);
System.out.println("2x:"+points[2].x + " 2y:" + points[2].y + " 3x:"+points[3].x + " 3y:" + points[3].y);

Вывод этих команд:

0x:0 0y:0 1x:30 1y:40
2x:50 2y:60 3x:70 3y:80

Итак, как вы можете видеть, структура точек в позиции 0 не имеет значений для x или y (она имеет 0 и 0 и должна быть 10 и 20). Почему это происходит? Как я могу это исправить?

Ответы [ 2 ]

2 голосов
/ 13 марта 2012

Ваши данные структуры неинициализированы, потому что вы никогда не вызываете Structure.read () после инициализации структуры из значения указателя.

В некоторых случаях JNA неявно вызывает для вас Structure.read (), например, до / после вызова нативной функции или при развертывании одной структуры в массив, поддерживаемый той же памятью.В последнем случае, однако, ваш первый элемент неинициализирован, потому что JNA предполагает, что он уже инициализирован, когда вы вызываете toArray () для него.

Когда вы объявляете, что ваша функция возвращает Structure, а не Pointer, JNAможет догадаться, что вам нужно вызвать Structure.read () для вас.

0 голосов
/ 13 марта 2012

по причине того, что возвращаемая структура является указателем, поэтому вы должны сообщить jna, что возвращаемый тип является указателем структуры, вы должны объявить, что вы реализуете Structure.ByReference и Structure.ByValue

public class Point extends Structure {
public static class ByReference extends Point implements Structure.ByReference { }

public static class ByValue extends Point implements Structure.ByValue{ }

public Point() {
// required for toArray()
}

public Point(Pointer pointer) {
    super(pointer);
}

public int x, y;
}

затем

public interface Multiplyt extends Library{
Point.ByReference getPoints();
}

Point.ByReference - это то же самое, что Point * в языке C, который может анализировать jna

Point.ByReference pointer = test.getPoints();
Point points[];
points = (Point[]) pointer.toArray(4);
System.out.println("0x:"+points[0].x + " 0y:" + points[0].y + " 1x:"+ points[1].x + " 1y:" + points[1].y);
System.out.println("2x:"+points[2].x + " 2y:" + points[2].y + " 3x:"+points[3].x + " 3y:" + points[3].y);
...