common-lispsbclcffi

Using CFFI in Common Lisp, calling functions returning pointers


I am using SBCL, and trying to use CFFI. I started following the manual here but I kept getting that the function curl_easy_init is undefined, so I decided to try a simpler case.

Some functions work as expected, while others seem to be not defined. This is explained below:

Here is my C code:

#include <stdio.h>
#include <stdlib.h>

/* "Works" except output doesn't appear. Not important for now */
void hello()
{
  printf("Hello World\n");
}

/* Works as expected */
float add(float x1, float x2)
{
  return x1 + x2;
}

/* appears to not be defined in SBCL*/
void* init_this()
{
  return malloc(10);
}

/* Appears to not be defined in SBCL*/
void clean_this(void* ptr)
{
  free(ptr);
}

This C file is compiled as:

gcc -shared -o cffi_test.so -fPIC cffi_test.c

My Common Lisp code:

(quicklisp:quickload "cffi")

(defpackage :my-cffi
  (:use :common-lisp :cffi))

(in-package :my-cffi)
(export '(hello add init_this clean_this))


(define-foreign-library cffi_test
  (t (:default "~/Work/clisp/cffi_test")))

(use-foreign-library cffi_test)

(defcfun "hello" :void)
(defcfun "add" :float (x1 :float ) (x2 :float))
(defcfun "init_this" :pointer)
(defcfun "clean_this" :void (handle :pointer))

What I get as I expect:

* (my-cffi:add 3.0 4.0)

7.0

What appears to be a problem:

(my-cffi:init_this)

Generates the error:

The function MY-CFFI:INIT_THIS is undefined.
   [Condition of type UNDEFINED-FUNCTION]

...

Backtrace:
  0: (SB-IMPL::RETRY-%COERCE-NAME-TO-FUN MY-CFFI:INIT_THIS NIL)
      Locals:
        SB-IMPL::NAME = MY-CFFI:INIT_THIS
        SB-IMPL::STRICTLY-FUNCTIONP = NIL

I get same error for clean_this , and in the link above, following the manual, for curl_easy_init which inspired this experiment.


Solution

  • A foreign name given as a string to CFFI:DEFCFUN will be converted into a lispier name using the generic function CFFI:TRANSLATE-NAME-FROM-FOREIGN. The default behavior is to change underscores to hyphens:

    CL-USER> (cffi:translate-name-from-foreign "mylib_fun_name" *package*)
    MYLIB-FUN-NAME
    

    You can also give a lisp name explicitly in the function definition:

    (defcfun ("mylib_fun_name" fun-name) ...)