Packed Record из делфи в Java
Всем привет! Столкнулся с проблемой вызова запакованной записи из DLL, написанной на делфи. Есть функция в делфи, которая использует как аргумент запакованную запись:
type
{информация о счёте}
TAccountInfo = packed record
Size : Word; // SizeOf( TAccountInfo )
Account : Integer; // номер счёта
Card : Int64; // номер карты
Holder : Array[0..40] of Char; //ФИО
Scheme : Byte; {тип счёта: 0 - ручное пополнение без ограничения оплат 1 - автоматическое пополнение без ограничения оплат
2 - автоматическое пополнение с лимитом оплат на один день
3 - автоматическое пополнение с лимитом оплат на неделю
4 - автоматическое пополнение с лимитом оплат на месяц
5 - ручное пополнение с лимитом оплат на один день
6 - ручное пополнение с лимитом оплат на неделю
7 - ручное пополнение с лимитом оплат на месяц
}
Offered : Integer; // дата выдачи (0 -> 30/12/1899)
Expired : Integer; // срок действия
Birthday : Integer; // день рождения
Deleted : BOOL; // счёт удален?
Locked : BOOL; // карта заблокирована?
Seize : BOOL; // карту изъять?
WhyLocked : Array[0..255] of Char; // причина блокировки - asciiz
Discount : Word; // номер скидки
Bonus : Word; // номер бонуса
PayLimit : Comp; // лимит оплат для счетов c лимитом
Female : BOOL; // пол
Folder : Word; // идентификатор отдела
Unpay : Integer; // номер неплательщика
Tel1 : Array[0..15] of Char; //телефон 1
Tel2 : Array[0..15] of Char; //телефон 2
Email : Array[0..255] of Char;
Address : Array[0..255] of Char;
DopInfo : Array[0..255] of Char; //произвольная информация - asciiz
Balance : Comp; // для карт с ручным пополнением - текущий остаток
end;
{получить информацию о счёте}
Function GetAccountInfo( Account: Integer; var Info: TAccountInfo ): BOOL; stdcall;
При вызове функции GetAccountInfo указывается номер счёта, а затем требуется разметка для получения записи. Пробовал использовать структуру, но в ответ получаю сообщение из функции получения сообщения от DLL:
Invalid record size
либо ошибку чтения памяти. При выводе из структуры записи имеют значение 0.
Ниже прикладываю свой код на Java:
//Вызов в интерфейсе CscLink
@Structure.FieldOrder({
"account", "adress", "balance", "birthday", "bonus", "card",
"deleted", "discount", "dopInfo", "email", "expired", "folder",
"holder", "locked", "offered", "payLimit", "scheme", "seize", "sex",
"size", "tel1", "tel2", "unpay", "whyLocked"})
public class TAccountInfo extends Structure{
public char size;
public int account;
public long card;
public char[] holder = new char[40];
public byte scheme;
public int offered;
public int expired;
public int birthday;
public boolean deleted;
public boolean locked;
public boolean seize;
public char[] whyLocked = new char[255];
public char discount;
public char bonus;
public long payLimit;
public boolean sex;
public char folder;
public int unpay;
public char[] tel1 = new char[15];
public char[] tel2 = new char[15];
public char[] email = new char[255];
public char[] adress = new char[255];
public char[] dopInfo = new char[255];
public long balance;
}
//Вызов в Main
CscLink.TAccountInfo taco = new CscLink.TAccountInfo();
myLib.GetAccountInfo(getAccNumb.getValue(), taco);
System.out.println(taco.card);
Ответы (1 шт):
Вывод packed record через JNA в Java производится следующим образом. Вывод производится с помощью структуры. В запакованной записи первый аргумент (Size, в конкретном случае) отвечает за размерность всей структуры, туда мы и передаём размер из delphi (sizeof всей структуры packed record).
@Structure.FieldOrder({"Size", "Account", "Card", "Holder", "Scheme", "Offered", "Expired", "Birthday", "Deleted","Locked", "Seize", "WhyLocked", "Discount", "Bonus", "PayLimit", "Female", "Folder", "Unpay", "Tel1", "Tel2", "Email", "Address", "DopInfo", "Balance"})
public class TAccountInfo extends Structure{
//В конкретном случае 1166 байт
public char Size = 1166;
public int Account;
public byte[] Card = new byte[32];
public byte[] Holder = new byte[50];
public byte Scheme;
public int Offered;
public int Expired;
public int Birthday;
public boolean Deleted;
public boolean Locked;
public boolean Seize;
public byte[] WhyLocked = new byte[255];
public char Discount;
public char Bonus;
public long PayLimit;
public boolean Female;
public short Folder;
public int Unpay;
public byte[] Tel1 = new byte[15];
public byte[] Tel2 = new byte[15];
public byte[] Email = new byte[255];
public byte[] Address = new byte[255];
public byte[] DopInfo = new byte[255];
public long Balance;
}
Далее мы выполняем соответствия типов и инициализируем массивы. Ниже приведу использованные значения для маппинга.
+---------------------+---------------------------+
| Delphi | Java |
+---------------------+---------------------------+
| Word | char или short |
| Int64 | long |
| Array[0..n] of Char | byte[] name = new byte[n] |
| BOOL | boolean |
| Comp | long |
| Byte | byte |
+---------------------+---------------------------+
Остальные типы приводятся в соответствии с размерностью байтов.