foreign-object.scm 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. ;;; Wrapping foreign objects in Scheme
  2. ;;; Copyright (C) 2014, 2015 Free Software Foundation, Inc.
  3. ;;;
  4. ;;; This library is free software; you can redistribute it and/or
  5. ;;; modify it under the terms of the GNU Lesser General Public
  6. ;;; License as published by the Free Software Foundation; either
  7. ;;; version 3 of the License, or (at your option) any later version.
  8. ;;;
  9. ;;; This library is distributed in the hope that it will be useful,
  10. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;;; Lesser General Public License for more details.
  13. ;;;
  14. ;;; You should have received a copy of the GNU Lesser General Public
  15. ;;; License along with this library; if not, write to the Free Software
  16. ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. ;;;
  18. ;;; Commentary:
  19. ;;
  20. ;;
  21. ;;; Code:
  22. (define-module (system foreign-object)
  23. #:use-module (oop goops)
  24. #:export (make-foreign-object-type
  25. define-foreign-object-type))
  26. (eval-when (eval load expand)
  27. (load-extension (string-append "libguile-" (effective-version))
  28. "scm_init_foreign_object"))
  29. (define-class <foreign-class> (<class>))
  30. (define-class <foreign-class-with-finalizer> (<foreign-class>)
  31. (finalizer #:init-keyword #:finalizer #:init-value #f
  32. #:getter finalizer))
  33. (define-method (allocate-instance (class <foreign-class-with-finalizer>)
  34. initargs)
  35. (let ((instance (next-method))
  36. (finalizer (finalizer class)))
  37. (when finalizer
  38. (%add-finalizer! instance finalizer))
  39. instance))
  40. (define* (make-foreign-object-type name slots #:key finalizer
  41. (getters (map (const #f) slots)))
  42. (unless (symbol? name)
  43. (error "type name should be a symbol" name))
  44. (unless (or (not finalizer) (procedure? finalizer))
  45. (error "finalizer should be a procedure" finalizer))
  46. (let ((dslots (map (lambda (slot getter)
  47. (unless (symbol? slot)
  48. (error "slot name should be a symbol" slot))
  49. (cons* slot #:class <foreign-slot>
  50. #:init-keyword (symbol->keyword slot)
  51. #:init-value 0
  52. (if getter (list #:getter getter) '())))
  53. slots
  54. getters)))
  55. (if finalizer
  56. (make-class '() dslots #:name name
  57. #:finalizer finalizer
  58. #:static-slot-allocation? #t
  59. #:metaclass <foreign-class-with-finalizer>)
  60. (make-class '() dslots #:name name
  61. #:static-slot-allocation? #t
  62. #:metaclass <foreign-class>))))
  63. (define-syntax define-foreign-object-type
  64. (lambda (x)
  65. (define (kw-apply slots)
  66. (syntax-case slots ()
  67. (() #'())
  68. ((slot . slots)
  69. (let ((kw (symbol->keyword (syntax->datum #'slot))))
  70. #`(#,kw slot . #,(kw-apply #'slots))))))
  71. (syntax-case x ()
  72. ((_ name constructor (slot ...) kwarg ...)
  73. #`(begin
  74. (define slot (ensure-generic 'slot (and (defined? 'slot) slot)))
  75. ...
  76. (define name
  77. (make-foreign-object-type 'name '(slot ...) kwarg ...
  78. #:getters (list slot ...)))
  79. (define constructor
  80. (lambda (slot ...)
  81. (make name #,@(kw-apply #'(slot ...))))))))))