]> git.jsancho.org Git - guile-irrlicht.git/blob - irrlicht/util.scm
Foreign records (in C) (WIP)
[guile-irrlicht.git] / irrlicht / util.scm
1 ;;; guile-irrlicht --- FFI bindings for Irrlicht Engine
2 ;;; Copyright (C) 2019 Javier Sancho <jsf@jsancho.org>
3 ;;;
4 ;;; This file is part of guile-irrlicht.
5 ;;;
6 ;;; Guile-irrlicht is free software; you can redistribute it and/or modify
7 ;;; it under the terms of the GNU Lesser General Public License as
8 ;;; published by the Free Software Foundation; either version 3 of the
9 ;;; License, or (at your option) any later version.
10 ;;;
11 ;;; Guile-irrlicht is distributed in the hope that it will be useful, but
12 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ;;; General Public License for more details.
15 ;;;
16 ;;; You should have received a copy of the GNU Lesser General Public
17 ;;; License along with guile-irrlicht.  If not, see
18 ;;; <http://www.gnu.org/licenses/>.
19
20
21 (define-module (irrlicht util)
22   #:use-module (system foreign)
23   #:use-module (srfi srfi-9)
24   #:use-module (srfi srfi-9 gnu)
25   #:export (bool->integer
26             integer->bool
27             define-foreign
28             define-foreign-record-type))
29
30 (define (bool->integer var)
31   (if var 1 0))
32
33 (define (integer->bool var)
34   (if (= var 0) #f #t))
35
36 ;; Based on guile-sdl2 function, thanks a lot
37 (define irrlicht-func
38   (let ((cirr (dynamic-link "libCIrrlicht")))
39     (lambda (return-type function-name arg-types)
40       (pointer->procedure return-type
41                           (dynamic-func function-name cirr)
42                           arg-types))))
43
44 (define-syntax-rule (define-foreign name return-type func-name arg-types)
45   (define-public name
46     (irrlicht-func return-type func-name arg-types)))
47
48 ;; foreign struct record type
49 (define-record-type standard-foreign-record-type
50   (make-foreign-record-type name types fields)
51   foreign-record-type?
52   (name foreign-record-type-name)
53   (types foreign-record-type-types)
54   (fields foreign-record-type-fields))
55
56 (define-record-type foreign-record
57   (make-foreign-record type pointer)
58   foreign-record?
59   (type foreign-record-type)
60   (pointer foreign-record-pointer set-foreign-record-pointer!))
61
62 (set-record-type-printer! foreign-record
63   (lambda (record port)
64     (format port "#<~a" (foreign-record-type-name (foreign-record-type record)))
65     (let* ((pointer (foreign-record-pointer record))
66            (record-type (foreign-record-type record))
67            (types (foreign-record-type-types record-type))
68            (fields (foreign-record-type-fields record-type))
69            (values (parse-c-struct pointer types)))
70       (for-each (lambda (field value)
71                   (format port " ~a: ~a" field value))
72                 fields
73                 values))
74     (format port ">")))
75
76 (define-syntax define-foreign-record-type
77   (lambda (x)
78     (define (field-names field-specs)
79       (map (lambda (field-spec)
80              (syntax-case field-spec ()
81                ((name type getter) #'name)
82                ((name type getter setter) #'name)))
83            field-specs))
84     (define (field-types field-specs)
85       (map (lambda (field-spec)
86              (syntax-case field-spec ()
87                ((name type getter) #'type)
88                ((name type getter setter) #'type)))
89            field-specs))
90     (syntax-case x ()
91       ((_ name (make-name make-arg ...) predicate? field-spec ...)
92        (with-syntax (((type-id ...) (field-types #'(field-spec ...)))
93                      ((field-name ...) (field-names #'(field-spec ...))))
94          #'(begin
95              (define name
96                (make-foreign-record-type
97                 'name
98                 (list type-id ...)
99                 (list 'field-name ...)))
100              (define (make-name make-arg ...)
101                (let* ((types (foreign-record-type-types name))
102                       (c-struct-pointer (make-c-struct types (list make-arg ...))))
103                  (make-foreign-record name c-struct-pointer)))
104              (define (predicate? record)
105                (and
106                 (foreign-record? record)
107                 (let* ((record-type (foreign-record-type record))
108                        (type-name (foreign-record-type-name record-type)))
109                   (equal? type-name (foreign-record-type-name name)))))
110              (export name)
111              (export make-name)
112              (export predicate?)))))))