I'm not a frequent nim user, but this is a feature I have been looking forwards
to since my first nim project in 2016.
My usecase - I would like to compile bpf filters at compile time to attach to
sockets, and I don't want to rely on libpcap being installed on target systems.
My code looks like this:
proc compile_filter*(filter: string): Filter {.compileTime.} =
## Gets a bpf string and uses libpcap to convert it to
## an array of bpf instructions.
##
## To compile the filter we use an external compiled (nim) program that
## uses pcap. In future versions of nim we will be able to use the
## ffi at compile time and then won't even need the external program
let prog = gorge("../tools/compile_filter \"" & filter & "\"").split("\n")
result = @[]
try:
for instruction in prog:
let parts = instruction.split(" ")
result.add(sock_filter(code: parts[0].parseInt.uint16,
jt: parts[1].parseInt.uint8,
jf: parts[2].parseInt.uint8,
k: parts[3].parseInt.uint32))
except:
raise newException(InvalidFilterError, "Invalid filter " & filter)
Run
and the important part of compile_filter minus types and boilerplate looks like
this:
proc pcap_compile*(p: pcap_t; fp: ptr sock_fprog, str: cstring, optimize:
int, netmask: int): cint {.importc, cdecl, header: "<pcap/pcap.h>".}
when isMainModule:
if paramCount() != 1:
echo "Usage: " & paramStr(0) & " filter"
quit(1)
var program: sock_fprog
let p* = pcap_open_dead(1, 65536)
if p == nil:
raiseOSError(osLastError())
if pcap_compile(p, addr program, paramStr(1), 1, 0) != 0:
raiseOSError(osLastError())
for i in 0..program.len-1:
echo program.filter[i]
pcap_freecode(addr program)
Run
This lets me write code like:
let filter = compile_filter("udp port 1234")
sock.attach_filter(filter)
Run
The major advantage of having the FFI be available at compile time is not
having to convert my data to a string in one program and then parsing the
string again back into an object at compile time.