dynlink.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /* Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. *
  3. * Authors: Mike Sperber, Marcus Crestani
  4. */
  5. #define NO_OLD_FFI 1
  6. /*
  7. * Dynamically load external modules on machines that support it.
  8. */
  9. #include "sysdep.h"
  10. #include <stdlib.h>
  11. #include <unistd.h>
  12. #include <string.h>
  13. #include "scheme48.h"
  14. #if defined(HAVE_DLOPEN)
  15. #include <dlfcn.h>
  16. #else
  17. #include "fake/dlfcn.h"
  18. #endif
  19. #if defined(RTLD_NOW)
  20. #define DLOPEN_MODE RTLD_NOW
  21. #elif defined(RTLD_LAZY)
  22. #define DLOPEN_MODE (RTLD_LAZY)
  23. #else
  24. #define DLOPEN_MODE (1)
  25. #endif
  26. static s48_ref_t
  27. shared_object_dlopen(s48_call_t call, s48_ref_t name, s48_ref_t complete_name_p)
  28. {
  29. void *handle;
  30. s48_ref_t res;
  31. char *full_name;
  32. if (!s48_false_p_2(call, complete_name_p))
  33. {
  34. size_t len = strlen(s48_extract_byte_vector_readonly_2(call, name));
  35. full_name = s48_make_local_buf(call, len + 4);
  36. memcpy(full_name,
  37. s48_extract_byte_vector_readonly_2(call, name),
  38. len);
  39. memcpy(full_name + len,
  40. ".so",
  41. 4);
  42. }
  43. else
  44. full_name = s48_extract_byte_vector_readonly_2(call, name);
  45. handle = dlopen(full_name, DLOPEN_MODE);
  46. if (handle == NULL)
  47. s48_error_2(call, "shared_object_dlopen", (char *)dlerror(), 1,
  48. s48_enter_byte_string_2(call, full_name));
  49. res = s48_make_value_2(call, void *);
  50. s48_unsafe_extract_value_2(call, res, void *) = handle;
  51. return res;
  52. }
  53. static s48_ref_t
  54. shared_object_dlsym(s48_call_t call, s48_ref_t handle, s48_ref_t name)
  55. {
  56. const char *error;
  57. void *entry;
  58. void *native_handle;
  59. s48_ref_t res;
  60. char *native_name;
  61. native_handle = s48_extract_value_2(call, handle, void *);
  62. native_name = s48_extract_byte_vector_readonly_2(call, name);
  63. entry = dlsym(native_handle, native_name);
  64. if (entry == NULL)
  65. s48_error_2(call, "shared_object_dlsym", (char*)dlerror(), 2, handle, name);
  66. res = s48_make_value_2(call, void *);
  67. s48_unsafe_extract_value_2(call, res, void *) = entry;
  68. return res;
  69. }
  70. static s48_ref_t
  71. shared_object_dlclose(s48_call_t call, s48_ref_t handle)
  72. {
  73. void *native_handle = s48_extract_value_2(call, handle, void *);
  74. if (dlclose(native_handle) < 0)
  75. s48_error_2(call, "shared_object_dlclose", (char*)dlerror(), 1, handle);
  76. return s48_unspecific_2(call);
  77. }
  78. typedef void (*thunk)();
  79. static s48_ref_t
  80. shared_object_call_thunk(s48_call_t call, s48_ref_t value)
  81. {
  82. thunk entry;
  83. entry = s48_extract_value_2(call, value, thunk);
  84. entry();
  85. return s48_unspecific_2(call);
  86. }
  87. void
  88. s48_init_dynlink(void)
  89. {
  90. S48_EXPORT_FUNCTION(shared_object_dlopen);
  91. S48_EXPORT_FUNCTION(shared_object_dlsym);
  92. S48_EXPORT_FUNCTION(shared_object_dlclose);
  93. S48_EXPORT_FUNCTION(shared_object_call_thunk);
  94. }