Converting a C struct to FFI::Struct
I am having difficulty setting up a struct from the pcap library in FFI.
Struct:
struct pcap_if {
struct pcap_if *next;
char *name;
char *description;
struct pcap_addr *addresses;
bpf_u_int32 flags; 开发者_JAVA百科
};
The relevant Ruby code
module Pcap
extend FFI::Library
ffi_lib 'pcap'
attach_function :pcap_findalldevs,[:pointer,:string],:int
class Pcap_if < FFI::Struct
layout :next,:pointer,
:name,:string,
:description,:string,
:pcap_addr,:pointer,
:flags,:int
end
end
Above attached function definition
int pcap_findalldevs(pcap_if_t **, char *)
The test code(run as root)
tmp=''
ptr = FFI::MemoryPointer.new :pointer
res = Pcap.pcap_findalldevs ptr,tmp
devs = Pcap::Pcap_if.new ptr
puts res
puts devs.offsets
puts devs[:name]
The output is
0 #pcap_findalldevs return success
next
0
name
4
description
8
pcap_addr
12
flags
16
pcap.rb:29:in `[]': Memory access offset=4 size=4 is out of bounds (IndexError)
The offsets look right to me but my C is very rusty. I was expecting 2 devices: lo and eth0 as names.
Slow post: Code should go like this:
ptr = FFI::MemoryPointer.new Pcap::Pcap_if.size
res = Pcap.pcap_findalldevs ptr,tmp
devs = Pcap::Pcap_if.new ptr
I found the solution. FFI can't deal with pcap_if_t **. I wrote a C function to return just an array of structs.
pcap_if_t* find_devs()
{
pcap_if_t *devs;
char errbuf[PCAP_ERRBUF_SIZE];
int res;
res=pcap_findalldevs(&devs, errbuf);
return devs;
}
I still need to handle error cases, but this does work.
精彩评论