changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/std/alien.lisp

changeset 119: 85f27597cf60
parent: cae8da4b1415
child: 2d1fe1d7b738
author: ellis <ellis@rwest.io>
date: Fri, 22 Dec 2023 18:43:53 -0500
permissions: -rw-r--r--
description: castable added, still testing
1 ;;; 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 (in-package :std)
23 ;; (reexport-from :sb-vm
24 ;; :include
25 ;; '(:with-pinned-objects :with-pinned-object-iterator :with-code-pages-pinned
26 ;; :sanctify-for-execution))
27 
28 (defmacro define-opaque (ty &optional no-export)
29  `(prog1
30  (define-alien-type ,ty (struct ,(symbolicate ty '-t)))
31  ,(unless no-export `(export '(,ty)))))
32 
33 (defun setfa (place from)
34  (loop for x across from
35  for i from 0 below (length from)
36  do (setf (deref place i) x)))
37 
38 (defun copy-c-string (src dest &aux (index 0))
39  (loop (let ((b (sb-sys:sap-ref-8 src index)))
40  (when (= b 0)
41  (setf (fill-pointer dest) index)
42  (return))
43  (setf (char dest index) (code-char b))
44  (incf index))))
45 
46 (defun clone-strings (list)
47  (with-alien ((x (* (* char))
48  (make-alien (* char) (length list))))
49  (unwind-protect
50  (labels ((populate (list index function)
51  (if list
52  (let ((array (sb-ext:string-to-octets (car list) :null-terminate t)))
53  (sb-sys:with-pinned-objects (array)
54  (setf (deref x index) (sap-alien (sb-sys:vector-sap array) (* char)))
55  (populate (cdr list) (1+ index) function)))
56  (funcall function))))
57  (populate list 0
58  (lambda ()
59  (loop for i below (length list)
60  do (print (cast (deref x i) c-string))))))
61  (free-alien x))))
62 
63 (defmacro clone-octets-to-alien (lispa aliena)
64  (with-gensyms (i)
65  `(loop for ,i from 0 below (length ,lispa)
66  do (setf (deref ,aliena ,i)
67  (aref ,lispa ,i)))))
68 
69 (defmacro clone-octets-from-alien (aliena lispa len)
70  (with-gensyms (i)
71  `(loop for ,i from 0 below ,len
72  do (setf (aref ,lispa ,i)
73  (deref ,aliena ,i)))))
74 
75 (defun foreign-int-to-integer (buffer size)
76  "Check SIZE of int BUFFER. return BUFFER."
77  (assert (= size (sb-alien:alien-size sb-alien:int :bytes)))
78  buffer)
79 
80 (defun foreign-int-to-bool (x size)
81  (if (zerop (foreign-int-to-integer x size))
82  nil
83  t))
84 
85 (defun bool-to-foreign-int (val)
86  (if val 1 0))
87 
88 ;;; Bits
89 (defun make-bits (length &rest args)
90  (apply #'make-array length (nconc '(:element-type bit) args)))
91 
92 ;;; Bytes
93 ;; (defmacro defbytes (&body bitsets)
94 ;; "For each cons-cell in BITSETS, define a new CAR-byte type for each
95 ;; member of CDR."
96 ;; `(loop for set in ',bitsets
97 ;; collect
98 ;; (let* ((ty (car set))
99 ;; (pfx
100 ;; (cond
101 ;; ((eq 'signed-byte ty) "I")
102 ;; ((eq 'unsigned-byte ty) "U")
103 ;; ((eq 'float ty) "F")
104 ;; (t (subseq (symbol-name ty) 0 1))))
105 ;; (nums (cdr set))
106 ;; r) ;result
107 ;; (setf r
108 ;; (mapc
109 ;; (lambda (x)
110 ;; `(deftype ,(symbolicate pfx (format 'nil "~a" x)) ()
111 ;; (cons ,ty ,x)))
112 ;; nums))
113 ;; (cons ty r))))
114 
115 ;; (defbytes
116 ;; (unsigned-byte 1 2 3 4 8 16 24 32 64 128)
117 ;; (signed-byte 2 3 4 8 16 24 32 64 128)
118 ;; (float 16 24 32 64 128))