changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/std/alien.lisp

changeset 82: a606978326c7
parent: 01f7dc4d7a8e
child: 17bdf95bc114
author: ellis <ellis@rwest.io>
date: Thu, 07 Dec 2023 22:40:32 -0500
permissions: -rw-r--r--
description: rocksdb ffi
1 ;;; std/alien.lisp --- foreign alien friends
2 
3 ;;; Commentary:
4 
5 ;; FFI in Lisp is somewhat different than FFI in other host langs. As
6 ;; such, we usually refer to our Lispy FFI interfaces inline with the
7 ;; CMUCL terminology: alien interfaces.
8 
9 ;; ref: https://www.sbcl.org/manual/#Foreign-Function-Interface for details
10 
11 ;; sb-alien is a high-level interface which automatically converts C
12 ;; memory pointers to lisp objects and back, but this can be slow for
13 ;; large or complex objects.
14 
15 ;; The lower-level interface is based on System Area Pointers (or
16 ;; SAPs), which provide untyped access to foreign memory.
17 
18 ;; Objects which can't be automatically converted into Lisp values are
19 ;; represented by objects of type ALIEN-VALUE.
20 
21 ;;; Code:
22 (uiop:define-package :std/alien
23  (:nicknames :alien)
24  (:use :cl :sb-vm :sb-ext :sb-c :std/base)
25  (:use-reexport :sb-alien)
26  (:export
27  :setfa
28  :copy-c-string
29  :clone-strings
30  :clone-octets-to-alien
31  :clone-octets-from-alien
32  :foreign-int-to-integer :foreign-int-to-bool :bool-to-foreign-int
33  :defbytes
34  :u1 :u2 :u3 :u4 :u8 :u16 :u24 :u32 :u64 :u128
35  :i2 :i3 :i4 :i8 :i16 :i24 :i32 :i64 :i128
36  :f16 :f24 :f32 :f64 :f128))
37 
38 (in-package :std/alien)
39 
40 ;; (reexport-from :sb-vm
41 ;; :include
42 ;; '(:with-pinned-objects :with-pinned-object-iterator :with-code-pages-pinned
43 ;; :sanctify-for-execution))
44 
45 (defun setfa (place from)
46  (loop for x across from
47  for i from 0 below (length from)
48  do (setf (deref place i) x)))
49 
50 (defun copy-c-string (src dest &aux (index 0))
51  (loop (let ((b (sb-sys:sap-ref-8 src index)))
52  (when (= b 0)
53  (setf (fill-pointer dest) index)
54  (return))
55  (setf (char dest index) (code-char b))
56  (incf index))))
57 
58 (defun clone-strings (list)
59  (with-alien ((x (* (* char))
60  (make-alien (* char) (length list))))
61  (unwind-protect
62  (labels ((populate (list index function)
63  (if list
64  (let ((array (sb-ext:string-to-octets (car list) :null-terminate t)))
65  (sb-sys:with-pinned-objects (array)
66  (setf (deref x index) (sap-alien (sb-sys:vector-sap array) (* char)))
67  (populate (cdr list) (1+ index) function)))
68  (funcall function))))
69  (populate list 0
70  (lambda ()
71  (loop for i below (length list)
72  do (print (cast (deref x i) c-string))))))
73  (free-alien x))))
74 
75 (defmacro clone-octets-to-alien (lispa aliena)
76  (with-gensyms (i)
77  `(loop for ,i from 0 below (length ,lispa)
78  do (setf (deref ,aliena ,i)
79  (aref ,lispa ,i)))))
80 
81 (defmacro clone-octets-from-alien (aliena lispa len)
82  (with-gensyms (i)
83  `(loop for ,i from 0 below ,len
84  do (setf (aref ,lispa ,i)
85  (deref ,aliena ,i)))))
86 
87 (defun foreign-int-to-integer (buffer size)
88  "Check SIZE of int BUFFER. return BUFFER."
89  (assert (= size (sb-alien:alien-size sb-alien:int :bytes)))
90  buffer)
91 
92 (defun foreign-int-to-bool (x size)
93  (if (zerop (foreign-int-to-integer x size))
94  nil
95  t))
96 
97 (defun bool-to-foreign-int (val)
98  (if val 1 0))
99 
100 ;;; Bytes
101 (defmacro defbytes (&body bitsets)
102  "For each cons-cell in BITSETS, define a new CAR-byte type for each
103 member of CDR."
104  `(loop for set in ',bitsets
105  collect
106  (let* ((ty (car set))
107  (pfx
108  (cond
109  ((eq 'signed-byte ty) "I")
110  ((eq 'unsigned-byte ty) "U")
111  ((eq 'float ty) "F")
112  (t (subseq (symbol-name ty) 0 1))))
113  (nums (cdr set))
114  r) ;result
115  (setf r
116  (mapc
117  (lambda (x)
118  `(deftype ,(symbolicate pfx (format 'nil "~a" x)) ()
119  (cons ,ty ,x)))
120  nums))
121  (cons ty r))))
122 
123 (defbytes
124  (unsigned-byte 1 2 3 4 8 16 24 32 64 128)
125  (signed-byte 2 3 4 8 16 24 32 64 128)
126  (float 16 24 32 64 128))