100 lines
3.2 KiB
Plaintext
100 lines
3.2 KiB
Plaintext
;;;;
|
|
;;;; f f i . s t k -- Foreign Function Interface for STk
|
|
;;;;
|
|
;;;; Copyright © 1997-1999 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
|
|
;;;;
|
|
;;;; Permission to use, copy, modify, distribute,and license this
|
|
;;;; software and its documentation for any purpose is hereby granted,
|
|
;;;; provided that existing copyright notices are retained in all
|
|
;;;; copies and that this notice is included verbatim in any
|
|
;;;; distributions. No written agreement, license, or royalty fee is
|
|
;;;; required for any of the authorized uses.
|
|
;;;; This software is provided ``AS IS'' without express or implied
|
|
;;;; warranty.
|
|
;;;;
|
|
;;;; Author: Erick Gallesio [eg@unice.fr]
|
|
;;;; Creation date: 17-Sep-1997 12:35
|
|
;;;; Last file update: 3-Sep-1999 19:51 (eg)
|
|
|
|
|
|
(select-module STk)
|
|
|
|
(define (ffi:arg-type type return?)
|
|
(let ((type (if (and (pair? type) (eq? '* (cadr type)))
|
|
;; We have (:xxx *). If xxx=char return :string,
|
|
;; :dynamic-ptr otherwise
|
|
(if (eq? :char (car type)) :string :dynamic-ptr)
|
|
type)))
|
|
;; DO NOT CHANGE the following values without changing the correponding
|
|
;; constants in the file dynload.c!!!!
|
|
(case type
|
|
((:void) (if return?
|
|
0
|
|
(error "define-external: void argument forbidden")))
|
|
((:char) 1)
|
|
((:short) 2)
|
|
((:ushort) 3)
|
|
((:int) 4)
|
|
((:uint) 5)
|
|
((:long) 6)
|
|
((:ulong) 7)
|
|
((:float) 8)
|
|
((:double) 9)
|
|
((:static-ptr) 10)
|
|
((:dynamic-ptr) 11)
|
|
((:string) 12)
|
|
((:boolean) 13)
|
|
(else (error "define-external: bad type: ~S" type)))))
|
|
|
|
(define (ffi:interface-type type) ;available calling conventions
|
|
(case type
|
|
((:c) 0) ;args pushed right-to-left, caller pops
|
|
((:argc/argv) 1) ;argv pushed, then argc, caller pops
|
|
((:winapi) 2))) ;args pushed left-to-right, callee pops
|
|
|
|
(define (ffi:parse-arglist l)
|
|
(letrec ((aux (lambda (l names types)
|
|
(cond
|
|
((null? l) (list names types names))
|
|
((pair? l) (aux (cdr l)
|
|
(append names (list (caar l)))
|
|
(append types
|
|
(list (ffi:arg-type (cadar l) #f)))))
|
|
(else (list (append names l)
|
|
(append types (ffi:arg-type :void #t))
|
|
(append names (list l))))))))
|
|
(aux l '() '())))
|
|
|
|
|
|
(define-macro (define-external name args . l)
|
|
(let* ((args (ffi:parse-arglist args))
|
|
(lib-name (get-keyword :library-name l ""))
|
|
(entry-name (get-keyword :entry-name l (symbol->string name)))
|
|
(return-type (ffi:arg-type (get-keyword :return-type l :void) #t))
|
|
(interface (ffi:interface-type (get-keyword :interface l :C)))
|
|
(names (car args))
|
|
(types (cadr args))
|
|
(actuals (caddr args))
|
|
(prologue `(,(if (string=? lib-name "")
|
|
""
|
|
(string-append lib-name "." *shared-suffix*))
|
|
,entry-name
|
|
,return-type
|
|
',names
|
|
',types)))
|
|
|
|
`(define ,name (lambda ,names
|
|
,(if (list? names)
|
|
`(%call-external ,@prologue ,@(copy-tree actuals))
|
|
`(apply %call-external ,@prologue
|
|
,@(copy-tree actuals)))))))
|
|
|
|
(define (external-exists? entry . lib)
|
|
(apply %external-exists?
|
|
entry
|
|
(list (if (null? lib)
|
|
""
|
|
(string-append (car lib) "." *shared-suffix*)))))
|
|
|
|
(provide "ffi")
|