changelog shortlog graph tags branches changeset files file revisions raw help

Mercurial > core / annotate lisp/std/alien.lisp

changeset 149: 2d1fe1d7b738
parent: 85f27597cf60
child: 7f8880bd2ac6
author: ellis <ellis@rwest.io>
date: Sat, 30 Dec 2023 20:50:15 -0500
permissions: -rw-r--r--
description: ffi update to support darwin, smh
96
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
1
 ;;; alien.lisp --- foreign alien friends
5
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
2
 
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
3
 ;;; Commentary:
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
4
 
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
5
 ;; FFI in Lisp is somewhat different than FFI in other host langs. As
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
6
 ;; such, we usually refer to our Lispy FFI interfaces inline with the
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
7
 ;; CMUCL terminology: alien interfaces.
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
8
 
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
9
 ;; ref: https://www.sbcl.org/manual/#Foreign-Function-Interface for details
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
10
 
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
11
 ;; sb-alien is a high-level interface which automatically converts C
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
12
 ;; memory pointers to lisp objects and back, but this can be slow for
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
13
 ;; large or complex objects.
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
14
 
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
15
 ;; The lower-level interface is based on System Area Pointers (or
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
16
 ;; SAPs), which provide untyped access to foreign memory.
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
17
 
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
18
 ;; Objects which can't be automatically converted into Lisp values are
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
19
 ;; represented by objects of type ALIEN-VALUE.
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
20
 
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
21
 ;;; Code:
96
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
22
 (in-package :std)
5
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
23
 ;; (reexport-from :sb-vm
96
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
24
 ;;  	       :include
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
25
 ;;  	       '(:with-pinned-objects :with-pinned-object-iterator :with-code-pages-pinned
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
26
 ;;  		 :sanctify-for-execution))
5
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
27
 
149
2d1fe1d7b738 ffi update to support darwin, smh
ellis <ellis@rwest.io>
parents: 119
diff changeset
28
 (defun shared-object-name (name)
2d1fe1d7b738 ffi update to support darwin, smh
ellis <ellis@rwest.io>
parents: 119
diff changeset
29
   "Return a filename with the correct extension for a shared library
2d1fe1d7b738 ffi update to support darwin, smh
ellis <ellis@rwest.io>
parents: 119
diff changeset
30
 on Linux and Darwin."
2d1fe1d7b738 ffi update to support darwin, smh
ellis <ellis@rwest.io>
parents: 119
diff changeset
31
   (format nil "lib~a.~a" name #+darwin "dylib" #-darwin "so"))
2d1fe1d7b738 ffi update to support darwin, smh
ellis <ellis@rwest.io>
parents: 119
diff changeset
32
 
2d1fe1d7b738 ffi update to support darwin, smh
ellis <ellis@rwest.io>
parents: 119
diff changeset
33
 (defmacro define-alien-loader (name &optional export)
2d1fe1d7b738 ffi update to support darwin, smh
ellis <ellis@rwest.io>
parents: 119
diff changeset
34
   "Define a default loader function named load-NAME which calls
2d1fe1d7b738 ffi update to support darwin, smh
ellis <ellis@rwest.io>
parents: 119
diff changeset
35
 SB-ALIEN:LOAD-SHARED-OBJECT."
2d1fe1d7b738 ffi update to support darwin, smh
ellis <ellis@rwest.io>
parents: 119
diff changeset
36
   (let ((fname (sb-int:symbolicate 'load- name)))
2d1fe1d7b738 ffi update to support darwin, smh
ellis <ellis@rwest.io>
parents: 119
diff changeset
37
     `(prog1
2d1fe1d7b738 ffi update to support darwin, smh
ellis <ellis@rwest.io>
parents: 119
diff changeset
38
        (defun ,fname (&optional save)
2d1fe1d7b738 ffi update to support darwin, smh
ellis <ellis@rwest.io>
parents: 119
diff changeset
39
          (prog1 (sb-alien:load-shared-object (shared-object-name ',name) :dont-save (not save))
2d1fe1d7b738 ffi update to support darwin, smh
ellis <ellis@rwest.io>
parents: 119
diff changeset
40
            (pushnew ,(sb-int:keywordicate name) *features*)))
2d1fe1d7b738 ffi update to support darwin, smh
ellis <ellis@rwest.io>
parents: 119
diff changeset
41
        ,@(when export (list `(export '(,fname)))))))
2d1fe1d7b738 ffi update to support darwin, smh
ellis <ellis@rwest.io>
parents: 119
diff changeset
42
        
110
cae8da4b1415 rocksdb macrofication, fixes for RDB (C Strings will be the death of me), removed PWN - quicklisp package conflict, smh.
ellis <ellis@rwest.io>
parents: 96
diff changeset
43
 (defmacro define-opaque (ty &optional no-export)
cae8da4b1415 rocksdb macrofication, fixes for RDB (C Strings will be the death of me), removed PWN - quicklisp package conflict, smh.
ellis <ellis@rwest.io>
parents: 96
diff changeset
44
   `(prog1
cae8da4b1415 rocksdb macrofication, fixes for RDB (C Strings will be the death of me), removed PWN - quicklisp package conflict, smh.
ellis <ellis@rwest.io>
parents: 96
diff changeset
45
        (define-alien-type ,ty (struct ,(symbolicate ty '-t)))
cae8da4b1415 rocksdb macrofication, fixes for RDB (C Strings will be the death of me), removed PWN - quicklisp package conflict, smh.
ellis <ellis@rwest.io>
parents: 96
diff changeset
46
      ,(unless no-export `(export '(,ty)))))
88
17bdf95bc114 ffi tests
ellis <ellis@rwest.io>
parents: 82
diff changeset
47
 
82
a606978326c7 rocksdb ffi
ellis <ellis@rwest.io>
parents: 47
diff changeset
48
 (defun setfa (place from) 
a606978326c7 rocksdb ffi
ellis <ellis@rwest.io>
parents: 47
diff changeset
49
   (loop for x across from
a606978326c7 rocksdb ffi
ellis <ellis@rwest.io>
parents: 47
diff changeset
50
 	for i from 0 below (length from)
a606978326c7 rocksdb ffi
ellis <ellis@rwest.io>
parents: 47
diff changeset
51
 	do (setf (deref place i) x)))
a606978326c7 rocksdb ffi
ellis <ellis@rwest.io>
parents: 47
diff changeset
52
 
5
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
53
 (defun copy-c-string (src dest &aux (index 0))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
54
   (loop (let ((b (sb-sys:sap-ref-8 src index)))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
55
           (when (= b 0)
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
56
             (setf (fill-pointer dest) index)
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
57
             (return))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
58
           (setf (char dest index) (code-char b))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
59
           (incf index))))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
60
 
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
61
 (defun clone-strings (list)
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
62
   (with-alien ((x (* (* char))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
63
                   (make-alien (* char) (length list))))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
64
     (unwind-protect
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
65
          (labels ((populate (list index function)
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
66
                     (if list
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
67
                         (let ((array (sb-ext:string-to-octets (car list) :null-terminate t)))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
68
                           (sb-sys:with-pinned-objects (array)
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
69
                             (setf (deref x index) (sap-alien (sb-sys:vector-sap array) (* char)))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
70
                             (populate (cdr list) (1+ index) function)))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
71
                         (funcall function))))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
72
            (populate list 0
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
73
                      (lambda ()
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
74
                        (loop for i below (length list)
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
75
                              do (print (cast (deref x i) c-string))))))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
76
       (free-alien x))))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
77
 
82
a606978326c7 rocksdb ffi
ellis <ellis@rwest.io>
parents: 47
diff changeset
78
 (defmacro clone-octets-to-alien (lispa aliena)
a606978326c7 rocksdb ffi
ellis <ellis@rwest.io>
parents: 47
diff changeset
79
   (with-gensyms (i)
a606978326c7 rocksdb ffi
ellis <ellis@rwest.io>
parents: 47
diff changeset
80
     `(loop for ,i from 0 below (length ,lispa)
a606978326c7 rocksdb ffi
ellis <ellis@rwest.io>
parents: 47
diff changeset
81
         do (setf (deref ,aliena ,i)
a606978326c7 rocksdb ffi
ellis <ellis@rwest.io>
parents: 47
diff changeset
82
                  (aref ,lispa ,i)))))
47
01f7dc4d7a8e rocksdb macros
ellis <ellis@rwest.io>
parents: 18
diff changeset
83
 
82
a606978326c7 rocksdb ffi
ellis <ellis@rwest.io>
parents: 47
diff changeset
84
 (defmacro clone-octets-from-alien (aliena lispa len)
a606978326c7 rocksdb ffi
ellis <ellis@rwest.io>
parents: 47
diff changeset
85
   (with-gensyms (i)
a606978326c7 rocksdb ffi
ellis <ellis@rwest.io>
parents: 47
diff changeset
86
     `(loop for ,i from 0 below ,len
a606978326c7 rocksdb ffi
ellis <ellis@rwest.io>
parents: 47
diff changeset
87
            do (setf (aref ,lispa ,i)
a606978326c7 rocksdb ffi
ellis <ellis@rwest.io>
parents: 47
diff changeset
88
                  (deref ,aliena ,i)))))
47
01f7dc4d7a8e rocksdb macros
ellis <ellis@rwest.io>
parents: 18
diff changeset
89
 
5
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
90
 (defun foreign-int-to-integer (buffer size)
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
91
   "Check SIZE of int BUFFER. return BUFFER."
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
92
   (assert (= size (sb-alien:alien-size sb-alien:int :bytes)))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
93
   buffer)
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
94
 
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
95
 (defun foreign-int-to-bool (x size)
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
96
   (if (zerop (foreign-int-to-integer x size))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
97
       nil
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
98
       t))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
99
 
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
100
 (defun bool-to-foreign-int (val)
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
101
   (if val 1 0))
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
102
 
119
85f27597cf60 castable added, still testing
ellis <ellis@rwest.io>
parents: 110
diff changeset
103
 ;;; Bits
85f27597cf60 castable added, still testing
ellis <ellis@rwest.io>
parents: 110
diff changeset
104
 (defun make-bits (length &rest args)
85f27597cf60 castable added, still testing
ellis <ellis@rwest.io>
parents: 110
diff changeset
105
   (apply #'make-array length (nconc '(:element-type bit) args)))
85f27597cf60 castable added, still testing
ellis <ellis@rwest.io>
parents: 110
diff changeset
106
 
5
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
107
 ;;; Bytes
96
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
108
 ;; (defmacro defbytes (&body bitsets)
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
109
 ;;   "For each cons-cell in BITSETS, define a new CAR-byte type for each
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
110
 ;; member of CDR."
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
111
 ;;   `(loop for set in ',bitsets
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
112
 ;; 	 collect
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
113
 ;; 	 (let* ((ty (car set))
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
114
 ;; 		(pfx
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
115
 ;; 		  (cond
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
116
 ;; 		    ((eq 'signed-byte ty) "I")
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
117
 ;; 		    ((eq 'unsigned-byte ty) "U")
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
118
 ;; 		    ((eq 'float ty) "F")
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
119
 ;; 		    (t (subseq (symbol-name ty) 0 1))))
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
120
 ;; 		(nums (cdr set))
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
121
 ;; 		r) ;result
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
122
 ;; 	   (setf r
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
123
 ;; 		 (mapc
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
124
 ;; 		  (lambda (x)
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
125
 ;; 		    `(deftype ,(symbolicate pfx (format 'nil "~a" x)) ()
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
126
 ;; 		       (cons ,ty ,x)))
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
127
 ;; 		       nums))
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
128
 ;; 	   (cons ty r))))
5
6ce26a70a11e init std
ellis <ellis@rwest.io>
parents:
diff changeset
129
 
96
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
130
 ;; (defbytes
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
131
 ;;   (unsigned-byte 1 2 3 4 8 16 24 32 64 128)
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
132
 ;;   (signed-byte 2 3 4 8 16 24 32 64 128)
301fd45bbe73 big refactor of lisp code
ellis <ellis@rwest.io>
parents: 88
diff changeset
133
 ;;   (float 16 24 32 64 128))