首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Packet.dll获取mac地址(JNR-FFI)

Packet.dll获取mac地址(JNR-FFI)
EN

Stack Overflow用户
提问于 2018-09-09 03:16:57
回答 1查看 263关注 0票数 0

如何使用jnr-ffi将下面的函数映射到java?

布尔PacketRequest(LPADAPTER AdapterObject,布尔集,PPACKET_OID_DATA OidData);

示例(C):3/Examples/PacketDriver/GetMacAddress/GetMacAddress.c

代码语言:javascript
复制
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);
        }
    }

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-10 08:50:47

首先,要进行propper映射,您应该查看要映射的类型的定义。PacketRequest函数返回BOOLEAN变量。根据windows数据类型描述的说法,BOOLEAN被声明为typedef BYTE BOOLEAN;。这意味着您可以在java中使用byte类型作为函数类型。但是JNR还支持将boolean类型映射到或从本机byte映射。因此,这两个定义都是正确的:

  • byte PacketRequest (...)
  • boolean PacketRequest (...)

接下来,您需要映射参数。在这里也一样,看看这些定义,您就会知道要使用哪些类型。其结果将是:

代码语言:javascript
复制
boolean PacketRequest(Pointer AdapterObject, boolean set, PPACKET_OID_DATA OidData);

set参数被错误地声明为int。此外,最后一个字段的@Out注释告诉JNR传递一个空结构,而不将值复制到本机内存。因此,不会传递预先设置的值。

最后一个参数具有PPACKET_OID_DATA类型-a 结构

代码语言:javascript
复制
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内部类来定义struct字段。此规则包括数组定义。结构的正确定义如下所示:

代码语言:javascript
复制
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函数所做的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52241049

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档