dynlink.c 2.6 KB

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