dynamic-external.scm 4.7 KB

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