changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/std/alien.lisp

changeset 222: 83e823b80219
parent: 17c05cd3e549
child: fdea20982c25
author: Richard Westhaver <ellis@rwest.io>
date: Sun, 03 Mar 2024 20:50:37 -0500
permissions: -rw-r--r--
description: add os module
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 (shadowing-import '(sb-unix::syscall sb-unix::syscall* sb-unix::int-syscall sb-unix::with-restarted-syscall sb-unix::void-syscall) :std)
24 
25 ;; (reexport-from :sb-vm
26 ;; :include
27 ;; '(:with-pinned-objects :with-pinned-object-iterator :with-code-pages-pinned
28 ;; :sanctify-for-execution))
29 
30 (defun shared-object-name (name)
31  "Return a filename with the correct extension for a shared library
32 on Linux and Darwin."
33  #+darwin (format nil "/usr/local/lib/lib~a.dylib" name)
34  #-darwin (format nil "lib~a.so" name))
35 
36 (defun list-all-shared-objects ()
37  sb-alien::*shared-objects*)
38 
39 (defmacro define-alien-loader (name &optional export)
40  "Define a default loader function named load-NAME which calls
41 SB-ALIEN:LOAD-SHARED-OBJECT."
42  (let* ((fname (sb-int:symbolicate (format nil "~@:(load-~a~)" name))))
43  `(prog1
44  (defun ,fname (&optional save)
45  (prog1 (sb-alien:load-shared-object (shared-object-name ',name) :dont-save (not save))
46  (pushnew ,(sb-int:keywordicate (string-upcase name)) *features*)))
47  ,@(when export (list `(export '(,fname)))))))
48 
49 (defmacro define-opaque (ty &optional no-export)
50  `(prog1
51  (define-alien-type ,ty (struct ,(symbolicate ty '-t)))
52  ,(unless no-export `(export '(,ty)))))
53 
54 (defun setfa (place from)
55  (loop for x across from
56  for i from 0 below (length from)
57  do (setf (deref place i) x)))
58 
59 (defun copy-c-string (src dest &aux (index 0))
60  (loop (let ((b (sb-sys:sap-ref-8 src index)))
61  (when (= b 0)
62  (setf (fill-pointer dest) index)
63  (return))
64  (setf (char dest index) (code-char b))
65  (incf index))))
66 
67 (defun clone-strings (list)
68  (with-alien ((x (* (* char))
69  (make-alien (* char) (length list))))
70  (unwind-protect
71  (labels ((populate (list index function)
72  (if list
73  (let ((array (sb-ext:string-to-octets (car list) :null-terminate t)))
74  (sb-sys:with-pinned-objects (array)
75  (setf (deref x index) (sap-alien (sb-sys:vector-sap array) (* char)))
76  (populate (cdr list) (1+ index) function)))
77  (funcall function))))
78  (populate list 0
79  (lambda ()
80  (loop for i below (length list)
81  do (print (cast (deref x i) c-string))))))
82  (free-alien x))))
83 
84 (defun c-strings-to-string-list (c-strings)
85  (declare (type (alien (* c-string)) c-strings))
86  (let ((reversed-result nil))
87  (dotimes (i most-positive-fixnum)
88  (declare (type index i))
89  (let ((c-string (deref c-strings i)))
90  (if c-string
91  (push c-string reversed-result)
92  (return (nreverse reversed-result)))))))
93 
94 (defmacro clone-octets-to-alien (lispa aliena)
95  (with-gensyms (i)
96  `(loop for ,i from 0 below (length ,lispa)
97  do (setf (deref ,aliena ,i)
98  (aref ,lispa ,i)))))
99 
100 (defmacro clone-octets-from-alien (aliena lispa len)
101  (with-gensyms (i)
102  `(loop for ,i from 0 below ,len
103  do (setf (aref ,lispa ,i)
104  (deref ,aliena ,i)))))
105 
106 (defun foreign-int-to-integer (buffer size)
107  "Check SIZE of int BUFFER. return BUFFER."
108  (assert (= size (sb-alien:alien-size sb-alien:int :bytes)))
109  buffer)
110 
111 (defun foreign-int-to-bool (x size)
112  (if (zerop (foreign-int-to-integer x size))
113  nil
114  t))
115 
116 (defun bool-to-foreign-int (val)
117  (if val 1 0))