Packet.dll получить MAC-адрес (JNR-FFI)
Как можно сопоставить приведенную ниже функцию с java с помощью jnr-ffi?
BOOLEAN PacketRequest (LPADAPTER AdapterObject, BOOLEAN Set, PPACKET_OID_DATA OidData);
public interface NativeMappings {
public static class PPACKET_OID_DATA extends Struct {
public final UnsignedLong Oid = new UnsignedLong();
public final UnsignedLong Length = new UnsignedLong();
public final byte[] Data = new byte[6];
public PPACKET_OID_DATA(Runtime runtime) {
super(runtime);
}
}
Pointer PacketOpenAdapter(String AdapterName);
int PacketRequest(Pointer AdapterObject, int set, @Out PPACKET_OID_DATA OidData);
void PacketCloseAdapter(Pointer lpAdapter);
public static class Main {
public static void main(String[] args) {
NativeMappings mappings = LibraryLoader.create(NativeMappings.class).load("Packet");
Runtime runtime = Runtime.getRuntime(mappings);
Pointer adapterObject = mappings.PacketOpenAdapter("\\Device\\NPF_{53152A2F-39F7-458E-BD58-24D17099256A}");
PPACKET_OID_DATA oid_data = new PPACKET_OID_DATA(runtime);
oid_data.Oid.set(0x01010102L);
oid_data.Length.set(6L);
int status = mappings.PacketRequest(adapterObject, 0, oid_data);
if (status == 0) {
System.out.println("Fail.");
} else {
System.out.println("Success.");
}
mappings.PacketCloseAdapter(adapterObject);
}
}
}
1 ответ
Прежде всего, чтобы сделать правильное сопоставление, вы должны взглянуть на определения типов, которые вы отображаете. PacketRequest
функция возвращает BOOLEAN
переменная. Согласно описанию типа данных windows, BOOLEAN
объявлен как typedef BYTE BOOLEAN;
, Это означает, что вы можете использовать byte
Тип как тип функции в Java. Но JNR также поддерживает отображение boolean
введите в / из родного byte
, Так что оба определения верны:
byte PacketRequest (...)
boolean PacketRequest (...)
Далее необходимо сопоставить параметры. То же самое здесь, посмотрите на определения, и вы будете знать, какие типы использовать. Результат будет:
boolean PacketRequest(Pointer AdapterObject, boolean set, PPACKET_OID_DATA OidData);
set
параметр был неправильно объявлен как int
, Кроме того @Out
аннотация последнего поля указывает JNR передавать пустую структуру без копирования значений в собственную память. Таким образом, никакие предварительно установленные значения не будут переданы.
Последний параметр имеет PPACKET_OID_DATA
Тип - это структура.
struct _PACKET_OID_DATA {
ULONG Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h
///< for a complete list of valid codes.
ULONG Length; ///< Length of the data field
UCHAR Data[1]; ///< variable-lenght field that contains the information passed to or received
///< from the adapter.
};
Структурное отображение немного сложнее, чем для нативных типов. Вы не можете использовать типы Java здесь. Вместо этого вы должны использовать jnr.ffi.Struct
внутренние классы для определения структурных полей. Это правило включает определения массивов. Правильное определение для вашей структуры будет выглядеть так:
class PPACKET_OID_DATA extends Struct {
public final UnsignedLong Oid = new UnsignedLong();
public final UnsignedLong Length = new UnsignedLong();
public final Unsigned8[] Data = array(new Unsigned8[6]);
public PPACKET_OID_DATA(Runtime runtime) {
super(runtime);
}
}
Обратите внимание на это UCHAR
определение массива. Собственно этот тип определяется как unsigned char
так что для структуры JNR он будет отображаться в jnr.ffi.Strunc.Unsigned8
класс или jnr.ffi.Struct.BYTE
(что в значительной степени то же самое).
Чтобы объявить поле массива, вы должны инициализировать массив во время построения. Вам нужно использовать jnr.ffi.Struct#array(...)
функции, чтобы сделать это правильно. Это также означает, что вы должны знать размер массива. Пример показан выше.
Почему мы должны определить это так? Во время инициализации Struct
это какой-то указатель переменной длины. Каждое поле внутреннего класса, инициализированное в нем, резервирует свое собственное пространство, увеличивает максимальный размер этого указателя. Таким образом, каждое поле представляет собой "представление" некоторого фрагмента памяти со своим собственным способом взаимодействия с этой памятью (публичные методы). Но чтобы создать массив таких представлений, вам нужно заполнить пустой массив экземплярами представлений. Это только то, что array
функция делает.