Доступ к массиву объектов C ++ из Java с использованием JNI - PullRequest
0 голосов
/ 25 февраля 2019

После моего предыдущего вопроса и ответа Some Name , я хотел бы попробовать противоположный способ и улучшить предыдущий вопрос:

Iхотел бы сделать следующие шаги:

  1. Выделить буфер в Java
  2. Заполнить массив в C ++
  3. Редактировать значения в Java
  4. Doнекоторый перебор чисел в C ++
  5. Считывание значений в Java

Рассмотрим следующий класс в C ++:

#pragma once
#pragma pack(push, 8)
class Point
{

public:
    double x;
    double y;
    Point();
    virtual ~Point();

    void ebeProduct(Point &other) {
        x = x * other.x;
        y = y * other.y;
    }
};



Point::Point()
{
}


Point::~Point()
{
}

#pragma pack(pop)

Следующий фрагмент кода:

Point point = Point();
std::cout << "Size of Point: " << sizeof(Point) << std::endl;
std::cout << "Address is: " << &point << std::endl;
std::cout << "x address is: " << &(point.x) << " and offset is: " << (long long)&(point.x) - (long long)&point << std::endl;
std::cout << "y address is: " << &(point.y) << " and offset is: " << (long long)&(point.y) - (long long)&point << std::endl;

показывает следующий результат:

Size of Point: 24
Address is: 000000D45B0FF2C0
x address is: 000000D45B0FF2C8 and offset is: 8
y address is: 000000D45B0FF2D0 and offset is: 16

Так что теперь я могу предположить следующие размеры в Java:

final int NUMBER_OF_POINTS = 10;
final int SIZE_OF_POINT = 24;
final int X_OFFSET = 8;
final int Y_OFFSET = 16;

Далее я выделю область памяти, используя unsafe и вызовите public static native void allocatePoints(long address, int numberOfPoints); Чтобы заполнить их Point объектами:

long address = unsafe.allocateMemory(NUMBER_OF_POINTS * SIZE_OF_POINT);
allocatePoints(address, NUMBER_OF_POINTS);

Код C ++, который заполняет точки:

Point * points = (Point *) address;
for (int pointIndex = 0; pointIndex < numberOfPoints; pointIndex++) {
    new(points + pointIndex) Point();
}

Далее я заполню точкив Java с произвольными числами, основанными на заданных смещениях:

for (int i = 0; i < NUMBER_OF_POINTS; i++) {
  unsafe.putDouble(address + i * SIZE_OF_POINT + X_OFFSET, i);
  unsafe.putDouble(address + i * SIZE_OF_POINT + Y_OFFSET, i * 2);
}

Далее вызывается public static native void multiplyPoints();, который только ebe производит каждую секундуint с предыдущим.

Наконец, я напечатаю заданные значения в Java:

for (int i = 0; i < NUMBER_OF_POINTS; i++) {
  System.err.print(unsafe.getDouble(address + i * SIZE_OF_POINT + X_OFFSET));
  System.err.print(" ; ");
  System.err.println(unsafe.getDouble(address + i * SIZE_OF_POINT + Y_OFFSET));
}

Эти этапы на самом деле выводят правильные результаты.
У меня вопрос, если эти этапыразумно: могу ли я предположить, что данные смещения являются правильными (пока на той же машине), и что запись значений непосредственно в буфер в Java и чтение их из объектов в C ++ всегда будут давать правильные результаты?

1 Ответ

0 голосов
/ 27 февраля 2019

В целом я вижу три потенциальных подводных камня:

  1. Заполнение и таблицы внутри Point могут испортить размер : компилятор C ++ может решить выровнять элементыот Point до желаемого выравнивания (например, double хочет 8-байтовое выравнивание, в то время как char не определяет выравнивание.)

    Аналогично, если ваши объекты C ++ содержат какие-либо virtualметоды (как ваш пример), ваш объект будет иметь vtable на передней панели.Это необходимо учитывать при выделении памяти и доступе к отдельным элементам.

  2. Выравнивание Point может испортить шаг вашего массива : предположим, что последнийэлемент вашего класса имеет дополнительный char, тогда следующий элемент будет выровнен с ближайшим кратным 8 байтов.(другими словами, ваш шаг массива будет 8 + 8 + 1 (данные) + заполнение байтами +7)

    Это необходимо учитывать как при распределении памяти, так и при доступе к отдельным элементам.

  3. sun.misc.Unsafe уже в пути.Этот код может в конечном итоге перестать работать в JDK11 и выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...