dynamic-external.scm 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ;; More high-level interface to dynamic loading:
  3. ;; This automatically initializes an externals shared object, keeps
  4. ;; track of which shared objects are loaded, and prevents them from
  5. ;; being removed automatically by the GC.
  6. ;; The shared object must define a function
  7. ;; void s48_on_load(void);
  8. ;; It can also define functiosn:
  9. ;; void s48_on_unload(void);
  10. ;; which is called just before unloading, and
  11. ;; void s48_on_reload(void);
  12. ;; which is called after reloading.
  13. ;; (which typically do the same thing) that LOAD-DYNAMIC-EXTERNALS
  14. ;; calls, depending on whether the object is being loaded for the
  15. ;; first time or not.
  16. (define-record-type dynamic-externals :dynamic-externals
  17. (make-dynamic-externals shared-object
  18. complete-name?
  19. reload-on-repeat?
  20. reload-on-resume?)
  21. dynamic-externals?
  22. (shared-object dynamic-externals-shared-object
  23. set-dynamic-externals-shared-object!)
  24. (complete-name? dynamic-externals-complete-name?)
  25. (reload-on-repeat? dynamic-externals-reload-on-repeat?)
  26. (reload-on-resume? dynamic-externals-reload-on-resume?))
  27. (define *the-dynamic-externals-table* '())
  28. (define (find-dynamic-externals name)
  29. (let ((real-name (translate name)))
  30. (any (lambda (dynamic-externals)
  31. (string=? real-name
  32. (shared-object-name
  33. (dynamic-externals-shared-object
  34. dynamic-externals))))
  35. *the-dynamic-externals-table*)))
  36. ;; returns the DYNAMIC-EXTERNALS object
  37. (define (load-dynamic-externals name complete-name?
  38. reload-on-repeat? reload-on-resume?)
  39. (cond
  40. ((find-dynamic-externals name)
  41. => (lambda (dynamic-externals)
  42. ;; Should we respect the original settings for
  43. ;; RELOAD-ON-REPEAT? and RELOAD-ON-RESUME? or the new ones?
  44. ;; We assume they're always the same. We should probably
  45. ;; verify.
  46. (if reload-on-repeat?
  47. (reload-dynamic-externals-internal dynamic-externals #t))
  48. dynamic-externals))
  49. (else
  50. (let* ((shared-object (open-shared-object (translate name) complete-name?))
  51. (dynamic-externals (make-dynamic-externals shared-object
  52. complete-name?
  53. reload-on-repeat?
  54. reload-on-resume?)))
  55. (set! *the-dynamic-externals-table*
  56. (cons dynamic-externals
  57. *the-dynamic-externals-table*))
  58. (call-shared-object-address
  59. (shared-object-address shared-object "s48_on_load"))
  60. dynamic-externals))))
  61. (define (reload-dynamic-externals-internal dynamic-externals reload?)
  62. (let* ((old-shared-object (dynamic-externals-shared-object dynamic-externals))
  63. (name (shared-object-name old-shared-object)))
  64. (if reload?
  65. (unload-shared-object dynamic-externals))
  66. (let ((shared-object
  67. (open-shared-object (translate name)
  68. (dynamic-externals-complete-name? dynamic-externals))))
  69. (set-dynamic-externals-shared-object! dynamic-externals shared-object)
  70. (cond
  71. ((not reload?)
  72. (shared-object-address shared-object "s48_on_load"))
  73. ((shared-object-address shared-object "s48_on_reload")
  74. => call-shared-object-address)
  75. (else (shared-object-address shared-object "s48_on_load"))))))
  76. ;; for interactive usage
  77. (define (reload-dynamic-externals name)
  78. (cond
  79. ((find-dynamic-externals name) =>
  80. (lambda (dynamic-externals)
  81. (reload-dynamic-externals-internal dynamic-externals #t)))
  82. (else
  83. (error "trying to load dynamic externals that were never loaded" name))))
  84. ;; most common usage, when a Scheme package requires C externals to work
  85. (define (import-dynamic-externals name)
  86. (load-dynamic-externals name #t #f #t))
  87. ;; We can't do this via a reinitializer, because the reinitializer
  88. ;; will typically call external C code, which is typically in a shared
  89. ;; library. So we need to load the shared libraries before we run any
  90. ;; reinitializers.
  91. (add-initialization-thunk!
  92. (lambda ()
  93. (set! *the-dynamic-externals-table*
  94. (delete (lambda (dynamic-externals)
  95. (not (dynamic-externals-reload-on-resume? dynamic-externals)))
  96. *the-dynamic-externals-table*))
  97. (for-each (lambda (dynamic-externals)
  98. (reload-dynamic-externals-internal dynamic-externals #f))
  99. *the-dynamic-externals-table*)))
  100. ;; note this leaves the shared bindings in place.
  101. (define (unload-dynamic-externals dynamic-externals)
  102. (set! *the-dynamic-externals-table*
  103. (delq dynamic-externals *the-dynamic-externals-table*))
  104. (unload-shared-object dynamic-externals))
  105. (define (unload-shared-object dynamic-externals)
  106. (let ((shared-object (dynamic-externals-shared-object dynamic-externals)))
  107. (cond
  108. ((shared-object-address-or-false shared-object "s48_on_unload")
  109. => call-shared-object-address))
  110. (close-shared-object shared-object)))