How to send NULL as :string in cffi

Viewed 70

I'm trying to use wayland-client from lisp side, this is my code:

(define-foreign-library wayland-client
  (:unix (:or "libwayland-client.so.0.20.0" "libwayland-client.so"))
  (t (:default "libwayland-client")))


(use-foreign-library wayland-client)

(defcfun "wl_display_connect" :pointer
  (name :string))

(wl-display-connect (null-pointer));;return NULL

Code in C, come from here

#include <stdio.h>
#include <stdlib.h>
#include <wayland-client.h>

struct wl_display *display = NULL;

int main(int argc, char **argv) {

    display = wl_display_connect(NULL);
    if (display == NULL) {
    fprintf(stderr, "Can't connect to display\n");
    exit(1);
    }
    printf("connected to display\n");

    wl_display_disconnect(display);
    printf("disconnected from display\n");    
    exit(0);
}

I have test the C one and it worked, how should the lisp one be correct?

How wl_display_connect been defined from here

struct wl_display* wl_display_connect(const char *name)
1 Answers

I am not an expert on CFFI but I think the trick is to say that things are (:pointer :char)s not :strings. Given this trivial C function:

#include <stdio.h>

char *ts(char *x) {
  if (x == NULL) {
    printf("Got a null\n");
  }
  return x;
}

And this CFFI declaration:

(defcfun (ts "ts")
    (:pointer :char)
  (name (:pointer :char)))

Then this will work:

> (null-pointer-p (ts (null-pointer)))
Got a null
t

And you can then call it with foreign strings, but you need to deal with allocating and deallocating them: (ts "foo") won't work. But this will:

(defun ts-wrapper (s)
  (with-foreign-string (x s)
    (foreign-string-to-lisp (ts x))))

And now:

> (ts-wrapper "foo")
"foo"
3

Obviously in your case you don't need to deal with the conversion back from the foreign string.

Related