Переход с Delphi и Pascal на Java может быть непростой задачей, особенно когда дело касается работы с динамически подключаемыми библиотеками (DLL). В данной статье мы рассмотрим пример переезда части программы, написанной на Pascal в среде Delphi, в Java-программу. Основное внимание будет уделено решению проблем, связанных с использованием DLL в Java с помощью JNA (Java Native Access).
Проблема с DLL и некорректным доступом к памяти
Пользователь столкнулся с проблемой при попытке использовать функции, экспортируемые из DLL, в Java-программе. Проблема заключалась в том, что при вызове функции GetElev, которая должна была получить высоту над уровнем моря по координатам, возникал сбой с некорректным доступом к памяти.
Анализ функции GetElev
Функция GetElev объявлена в Delphi как процедура, принимающая два параметра типа Double и два параметра типа LongInt по ссылке. Это указывает на то, что все параметры передаются по ссылке, и результаты работы функции будут записаны в эти переменные. С помощью утилиты dumpbin.exe /EXPORTS была получена информация о функции GETELEV, экспортируемой из DLL Getelev.dll.
Работа с JNA
Используя JNA, пользователь смог частично интегрировать DLL в Java. Однако при вызове функции GETELEV возникла ошибка некорректного доступа к памяти. После исследования проблемы было предположено, что проблема может быть связана с неправильной настройкой маппингов в JNA или с тем, что JNA не поддерживает тип DLL, написанный на Pascal.
Подтвержденный ответ
Проблема была решена после того, как пользователь обновил свой Java-код следующим образом:
public interface LibraryCalls extends StdCallLibrary {
LibraryCalls INSTANCE = (LibraryCalls) Native.loadLibrary("getelev", LibraryCalls.class);
public void GETELEV(Pointer a, Pointer b, Pointer Elevate, Pointer ErrCode);
}
public static void main(String[] args) {
Pointer lat = new Memory(Native.getNativeSize(Double.TYPE));
lat.setDouble(0, 34.769823);
Pointer lon = new Memory(Native.getNativeSize(Double.TYPE));
lon.setDouble(0, -87.654147);
Pointer elevate = new Memory(Native.getNativeSize(Integer.TYPE));
elevate.setInt(0, 0);
Pointer errCode = new Memory(Native.getNativeSize(Integer.TYPE));
errCode.setInt(0, 0);
LibraryCalls newCall = LibraryCalls.INSTANCE;
newCall.GETELEV(lat, lon, elevate, errCode);
}
Ключевым моментом стало использование интерфейса StdCallLibrary и передача параметров по ссылке с помощью Pointer.
Альтернативный ответ
Необходимо понимать, что параметры, объявленные как var в Delphi, передаются по ссылке, и именно в них будет записан результат работы функции. В Java, с помощью JNA, необходимо соответствующим образом настроить параметры для передачи по ссылке.
Пример кода на Object Pascal (Delphi)
unit impdll;
interface
uses
Classes, Sysutils;
type
TChar80 = array[0..80] of char;
procedure GetElev(var a, b: Double; var Elevate, ErrCode: LongInt); stdcall;
...
implementation
procedure GetElev(var a, b: Double; var Elevate, ErrCode: LongInt); stdcall; external 'Getelev.dll' name 'GETELEV';
...
end.
Заключение
Переезд кода из Delphi в Java с использованием JNA для работы с DLL требует внимательного анализа параметров функций и их типов. В данной статье был представлен практический пример решения проблемы, с которой столкнулся пользователь, и даны рекомендации по корректной работе с JNA.
Примечание
В статье использованы примеры кода, отражающие типичные ситуации, с которыми можно столкнуться при работе с JNA и DLL, написанными на Pascal.
Переезд кода из Delphi и Pascal в Java, с использованием JNA для работы с DLL, требует внимательного изучения параметров функций и корректной настройки маппингов в JNA.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.