How to call a foreign function with an output pointer argument?

145 Views Asked by At

Let’s say there is a C function:

int do_something(int *output);

I can define it in lisp with cffi like this:

(cffi:defcfun ("do_something" %do-something)
   :int
   (output :pointer))

How can I call it and get the value of output? I have looked at other questions, but these are dealing with structs or unions, both of which do not apply in my case.

2

There are 2 best solutions below

2
coredump On BEST ANSWER

In your answer you probably have a memory leak because the allocated memory is never freed. See cffi:foreign-free which is used to "Free a PTR allocated by FOREIGN-ALLOC.". Typically you can use unwind-protect to call foreign-free:

(let ((output (cffi:foreign-alloc :int)))
  (unwind-protect (progn ...)
    (cffi:foreign-free output)))

Alternatively, you can use the following macro:

(cffi:with-foreign-object (output :int)
   ...)

Note that if you expand the macro it seems to be able to allocate memory on the stack (tested with SBCL), unlike the above version with foreign-alloc and foreign-free. I think these two functions are best used in cases where the lifetime of the object is more complex than what a lexical scope offers.

0
Philipp Ludwig On

Figured it out myself. cffi:foreign-alloc allows one to create an int, and cffi:mem-aref can be used to access the value, e.g.:

(let ((output (cffi:foreign-alloc :int)))
  (%do-something output)
  (format t "Result: ~a~%" (cffi:mem-aref output :int)))