如何在CFFI中向:string类型参数传递NULL?Wayland-Client库的Lisp调用适配方案
wl_display_connect Returning NULL in CFFI Code Let's break down why your current Lisp code is returning NULL and how to fix it.
The Root Cause
Your CFFI declaration for wl_display_connect defines the name parameter as :string, but this type expects a Lisp string object. When you pass (null-pointer) to it, CFFI doesn't handle this correctly—it tries to interpret the null pointer as a string, which leads to a mismatched type and the function failing to connect.
In C, passing NULL (a void pointer) to a const char* parameter works because pointers are compatible, but CFFI's type system needs explicit hints to handle this case.
The Fixes
You have two straightforward ways to adjust your CFFI code to match the C behavior:
Option 1: Declare the parameter as :pointer
This lets you directly pass (null-pointer) to represent C's NULL, just like your C code does:
(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) ;; Fix: Change name parameter type to :pointer (defcfun "wl_display_connect" :pointer (name :pointer)) ;; Add the disconnect function to clean up resources (defcfun "wl_display_disconnect" :void (display :pointer)) ;; Test the connection (let ((display (wl-display-connect (null-pointer)))) (if (null-pointer-p display) (format *error-output* "Can't connect to display~%") (progn (format t "connected to display~%") (wl-display-disconnect display) (format t "disconnected from display~%"))))
Option 2: Use (:nullable :string) for cleaner syntax
CFFI supports nullable types with the :nullable modifier. This lets you pass nil directly, which CFFI automatically converts to a C NULL pointer:
(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) ;; Fix: Use (:nullable :string) to accept nil as NULL (defcfun "wl_display_connect" :pointer (name (:nullable :string))) (defcfun "wl_display_disconnect" :void (display :pointer)) ;; Test with nil instead of (null-pointer) (let ((display (wl-display-connect nil))) (if (null-pointer-p display) (format *error-output* "Can't connect to display~%") (progn (format t "connected to display~%") (wl-display-disconnect display) (format t "disconnected from display~%"))))
Why This Works
Both options align the CFFI type system with the C function's signature:
:pointerdirectly matches theconst char*parameter's pointer nature, allowing null pointers to be passed correctly.(:nullable :string)tells CFFI that the string parameter can be NULL, so it safely convertsnilto the appropriate C NULL value.
Either approach should resolve the NULL return issue and let you connect to the Wayland display just like your working C code.
内容的提问来源于stack exchange,提问作者C-Entropy

