Я использовал C-библиотеку в своем Java-коде, используя JNA. У меня есть эти C-структуры, чьи члены мне нужно печатать на Java. Из-за выравнивания и заполнения памяти размер отличался от того, что я действительно ожидал. Поэтому я использовал прагма-пакет, и так выглядят структуры.
#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) PACK( typedef struct { size_t size; uint8_t bytes[48]; } ipj_tid_t); PACK( typedef struct { bool has_epc; //1 ipj_epc_t epc; //64+8 bool has_tid; //1 ipj_tid_t tid; //48+8 bool has_pc; //1 uint32_t pc; //4 bool has_xpc; //1 uint32_t xpc; //4 bool has_crc; //1 uint32_t crc; //4 bool has_timestamp; //1 uint64_t timestamp; //8 bool has_rssi; //1 int32_t rssi; //4 bool has_phase; //1 int32_t phase; //4 bool has_channel; //1 uint32_t channel; //4 bool has_antenna; //1 uint32_t antenna; //4 } ipj_tag); //total size= 174 PACK( typedef struct { bool has_error; ipj_error error; bool has_test_id; uint32_t test_id; bool has_result_1; uint32_t result_1; bool has_result_2; uint32_t result_2; bool has_result_3; uint32_t result_3; size_t data_count; uint32_t data[16]; bool has_timestamp; uint64_t timestamp; size_t lt_buffer_count; uint32_t lt_buffer[21]; } ipj_test_report); PACK( typedef struct { size_t size; uint8_t bytes[64]; } ipj_tag_operation_data_t); PACK( typedef struct { bool has_error; //1 ipj_error error; //4 bool has_tag; //1 ipj_tag tag; //174 bool has_tag_operation_type; //1 ipj_tag_operation_type tag_operation_type; //4 bool has_tag_operation_data; //1 ipj_tag_operation_data_t tag_operation_data; //72 bool has_retries; //1 uint32_t retries; //4 bool has_diagnostic; //1 uint32_t diagnostic; //4 bool has_timestamp; //1 uint64_t timestamp; //8 size_t lt_buffer_count; //8 uint32_t lt_buffer[30]; //120 } ipj_tag_operation_report); //405
Когда я запускаю код из Visual Studio, я не получаю никаких ошибок, исключений или сбоев от него. Но когда я называю это с Java, jvm рушится. Почему это происходит? В коде C есть и другие структуры, которые не упакованы. Это может быть причина? Пожалуйста посоветуй.
Структуры, которые я показал выше, используются в C. То, что возвращается из кода C, является этой структурой после всей обработки.
#define RX_MAX_SIZE 405 #pragma pack(push, 1) typedef struct _report { ipj_report_id report_id; uint32_t data_size; uint32_t data[RX_MAX_SIZE]; } report; #pragma pack(pop)
Эквивалентная структура JNA, которая была использована, выглядит следующим образом.
public class _report extends Structure { public static class ByValue extends _report implements Structure.ByValue { } public _report() { super(); setAlignType(ALIGN_NONE); } public _ipj_report_id reportid; public int data_size; public int[] data = new int[405]; @Override protected List getFieldOrder() { return Arrays.asList("reportid", "data_size", "data"); } } public class _ipj_report_id extends Structure { public int ipj_report_id; public _ipj_report_id() { super(); setAlignType(ALIGN_NONE); } @Override protected List getFieldOrder() { return Arrays.asList("ipj_report_id"); } }
Ниже приведена структура, которую я получаю при отладке кода JNA.
_report$ByValue(auto-allocated@0x18918cc0 (1628 bytes)) { _ipj_report_id reportid@0=_ipj_report_id(allocated@0x18918cc0 (4 bytes) (shared from auto-allocated@0x18918cc0 (1628 bytes))) { int ipj_report_id@0=0 } int data_size@4=195 int data[405]@8=[I@78bb0ecb }
Ниже я называю этот метод в JNA.
rfidlib rlib = (rfidlib) Native.loadLibrary("rfidlib", rfidlib.class); _report.ByValue report = new _report.ByValue(); report = rlib.get_next_reports();
JNA предполагает компоновку структуры по умолчанию для текущей целевой платформы (в данном случае, MS-компилятор).
Вы можете распечатать макет макета памяти, созданного JNA, вызвав Structure.toString()
после вызова JVM с помощью -Djna.dump_memory=true
.
Затем вы можете сравнить желаемую структуру структуры с фактическим расположением, созданным JNA, чтобы искать различия. Если вы в целом используете boolean
в своей структуре Java, по умолчанию используется выделение собственного int
, поэтому, если это не тот же размер, что и ваш собственный bool
, вам нужно либо использовать byte
на стороне Java, либо явно предоставить TypeMapper
для вашей Structure
чтобы указывают, что boolean
должно быть преобразовано в размер, совместимый с собственным bool
(обратите внимание, что размер native bool
не определяется стандартом C).
Я бы рекомендовал не использовать #pragma pack
в вашем коде, если вы его явно не нуждаетесь.
Обновите свой вопрос с помощью своей реализации Java Structure
и ее вывода отладки.