dynlink.c 2.4 KB

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