dynlink.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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. * Load DLLs on Windows.
  8. */
  9. #include <windows.h>
  10. #include "scheme48.h"
  11. #include "io.h"
  12. extern int s48_utf_8of16_to_utf_16(const unsigned char* utf_8of16,
  13. LPWSTR utf_16,
  14. int* errorp);
  15. static s48_ref_t
  16. shared_object_dlopen(s48_call_t call, s48_ref_t name, s48_ref_t complete_name_p)
  17. {
  18. HINSTANCE handle;
  19. s48_ref_t res;
  20. char *full_name;
  21. WCHAR* name_utf16;
  22. size_t len = strlen(s48_extract_byte_vector_readonly_2(call, name));
  23. if (!s48_false_p_2(call, complete_name_p))
  24. {
  25. full_name = s48_make_local_buf(call, len + 5);
  26. memcpy(full_name,
  27. s48_extract_byte_vector_readonly_2(call, name),
  28. len);
  29. memcpy(full_name + len,
  30. ".dll",
  31. 5);
  32. len += 4;
  33. }
  34. else
  35. full_name = s48_extract_byte_vector_readonly_2(call, name);
  36. name_utf16 = malloc(sizeof(WCHAR) * (len + 1));
  37. if (name_utf16 == NULL)
  38. s48_out_of_memory_error_2(call);
  39. s48_utf_8of16_to_utf_16(full_name, name_utf16, NULL);
  40. handle = LoadLibraryW(name_utf16);
  41. free(name_utf16);
  42. if (handle == NULL)
  43. s48_os_error_2(call, "shared_object_dlopen", GetLastError(), 1, name);
  44. res = s48_make_value_2(call, HINSTANCE);
  45. s48_set_value_2(call, res, HINSTANCE, handle);
  46. return res;
  47. }
  48. static s48_ref_t
  49. shared_object_dlsym(s48_call_t call, s48_ref_t handle, s48_ref_t name)
  50. {
  51. void *entry;
  52. HINSTANCE native_handle;
  53. char *native_name;
  54. native_handle = s48_extract_value_2(call, handle, HINSTANCE);
  55. native_name = s48_extract_byte_vector_readonly_2(call, name);
  56. entry = GetProcAddress(native_handle, native_name);
  57. if (entry == NULL)
  58. s48_os_error_2(call, "shared_object_dlsym", GetLastError(), 2,
  59. handle, name);
  60. return s48_enter_pointer_2(call, entry);
  61. }
  62. static s48_ref_t
  63. shared_object_dlclose(s48_call_t call, s48_ref_t handle)
  64. {
  65. HINSTANCE native_handle = s48_extract_value_2(call, handle, HINSTANCE);
  66. if (!FreeLibrary(native_handle) < 0)
  67. s48_os_error_2(call, "shared_object_dlclose", GetLastError(), 1, handle);
  68. return s48_unspecific_2(call);
  69. }
  70. typedef void (*thunk)();
  71. static s48_ref_t
  72. shared_object_call_thunk(s48_call_t call, s48_ref_t value)
  73. {
  74. thunk entry;
  75. entry = s48_extract_value_2(call, value, thunk);
  76. entry();
  77. return s48_unspecific_2(call);
  78. }
  79. void
  80. s48_init_dynlink(void)
  81. {
  82. S48_EXPORT_FUNCTION(shared_object_dlopen);
  83. S48_EXPORT_FUNCTION(shared_object_dlsym);
  84. S48_EXPORT_FUNCTION(shared_object_dlclose);
  85. S48_EXPORT_FUNCTION(shared_object_call_thunk);
  86. }