Skip to content

Instantly share code, notes, and snippets.

@lagagain
Last active October 23, 2024 02:29
Show Gist options
  • Save lagagain/df1b97eb08e57c2759c950efc3a2c7dd to your computer and use it in GitHub Desktop.
Save lagagain/df1b97eb08e57c2759c950efc3a2c7dd to your computer and use it in GitHub Desktop.
[practice] [Common Lisp] hello CFFI (Common Lisp + C)

This is a practice project to test Common Lisp + C with CFFI.

CFFI is a protocal for common lisp, and most popular impl like sbcl,ccl,cmucl,ecl and abcl have to this. So We can eazy to access C code from Common Lisp.

Env need

just only write for Linux(Unix) and need a lisp impl with cffi package. I pratice it with sbcl. You can install it with Roswell, or you can also ues more friendly env - cl-repl which also can install by roswell.

  • OS: Linux(Unix)
  • A Common lisp impl with cffi
  • C compiler
    • gcc
  • Make (or compile c file to library by self)

How to test

  1. First compile C to a library(.so).
  2. rum Common Lisp REPL
  3. load lisp file

compile C to a library

just type make to gen libhello.so file

make

run Common Lisp REPL

sbcl

use sbcl, or ccl, ecl,ros run,cl-repl et.

load lisp file

(load "hello")

Output

direct call c function
56
Hello, World
Hello, Bob
Hello, Andy
---------------------------
define c function, then call
56
Hello, World
Hello, Bob
---------------------------
change var a to 100,
then sccess a:100

call showA:100
#include<stdio.h>
#include<stdlib.h>
int a = 56;
void Hello(char *name){
printf("Hello, %s\n", name);
}
/* int main(void){ */
/* Hello("john"); */
/* } */
void HelloWorld(void){
printf("Hello, World\n");
}
void ShowA(void){
printf("%d\n", a);
}
(require :cffi)
;;(use-package :cffi)
(defun write-hr nil
(format t "~&---------------------------~&"))
;;; seting foreign library
(push '*default-pathname-defaults* cffi:*foreign-library-directories*) ;; Add current directory to search Paths, or when use 'use-foreign-library will not Found.
(cffi:define-foreign-library libhello
(:unix (:or "libhello.so.1" "libhello.so" "libhello.so.1.0.0")) ;; here can write as "./libhello.so" to select relative path file(current directory).
(t (:default "libhello")))
(cffi:use-foreign-library libhello) ;; use forenign or use `(cffi:load-foreign-library "./libhello.so"), the later not need to define-foreign-library
(cffi:defcvar ("a" a) :int "A C var named a") ;; access C var which named a
;;; direct call c function
(format t "direct call c function~&")
(cffi:foreign-funcall "ShowA")
(cffi:foreign-funcall "HelloWorld")
(cffi:with-foreign-string (name "Bob")
(cffi:foreign-funcall "Hello" :string name))
(cffi:foreign-funcall "Hello" :string "Andy")
(write-hr)
(format t "~&~&define c function, then call~&")
(cffi:defcfun ("ShowA" showA) :void )
(cffi:defcfun ("HelloWorld" hello-world) :void)
(cffi:defcfun ("Hello" hello) :void (name :string))
;; call c function
(showa)
(hello-world)
(hello "Bob")
(write-hr)
(format t "change var a to ~A,
then sccess a:~A~&
call showA:" (setf a 100) a)
(showA)
hello.so:
gcc hello.c -shared -fPIC -Wl,-soname,libhello.so.1 -o libhello.so.1.0.0
ln -rs libhello.so.1.0.0 libhello.so
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment