Baselib_DynamicLibrary.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #pragma once
  2. // Baselib Dynamic Library.
  3. // In computing, a dynamic linker is the part of an operating system that loads and links
  4. // the shared libraries needed by an executable when it is executed (at "run time"),
  5. // by copying the content of libraries from persistent storage to RAM, filling jump tables and
  6. // relocating pointers. The specific operating system and executable format determine how
  7. // the dynamic linker functions and how it is implemented.
  8. //
  9. // "Dynamic linker", Wikipedia: The Free Encyclopedia
  10. // https://en.wikipedia.org/w/index.php?title=Dynamic_linker&oldid=935827444
  11. //
  12. // Platform specific gotchas:
  13. // - On Posix/Darwin based platforms, if executable/library has import entries,
  14. // as for importing functions from .so's/.dylib's at executable/library open time,
  15. // Baselib_DynamicLibrary_GetFunction is able to return them as well.
  16. // This is because of ELF/Mach-O format limitations.
  17. // - On Posix/Darwin based platforms, to be able to query symbols in an executable
  18. // they must be made visible via --external-dynamic and -external_dynamic flags respectively.
  19. // Some linkers have an option to make specific symbols visible.
  20. // - Emscripten limitations are detailed in
  21. // https://github.com/emscripten-core/emscripten/wiki/Linking
  22. // - On some platforms dynamic linker doesn't load downstream dependencies.
  23. // For example if library A imports a symbol from library B,
  24. // and this is passed to the compiler/linker at compilation step,
  25. // on most platforms it will generate load entries inside library A to load library B,
  26. // so if you load library A then library B will be loaded for you by the dynamic linker.
  27. // But on some platforms, you have to load library B first, and then library A.
  28. #include "Baselib_ErrorState.h"
  29. #ifdef __cplusplus
  30. BASELIB_C_INTERFACE
  31. {
  32. #endif
  33. typedef struct Baselib_DynamicLibrary_Handle { intptr_t handle; } Baselib_DynamicLibrary_Handle;
  34. // values in range from 0 inclusive to -5 are valid handles on some platforms
  35. static const Baselib_DynamicLibrary_Handle Baselib_DynamicLibrary_Handle_Invalid = { -100 };
  36. #include <C/Baselib_DynamicLibrary.inl.h>
  37. // Open a dynamic library.
  38. //
  39. // Dynamic libraries are reference counted, so if the same library is loaded again
  40. // with Baselib_DynamicLibrary_OpenUtf8/Baselib_DynamicLibrary_OpenUtf16, the same file handle is returned.
  41. // It is also possible to load two different libraries containing two different functions that have the same name.
  42. //
  43. // Please note that additional error information should be retrieved via error state explain and be presented to the end user.
  44. // This is needed to improve ergonomics of debugging library loading issues.
  45. //
  46. // \param pathnameUtf8 Library file to be opened.
  47. // If relative pathname is provided, platform library search rules are applied (if any).
  48. // If nullptr is passed, Baselib_ErrorCode_InvalidArgument will be risen.
  49. //
  50. // Possible error codes:
  51. // - Baselib_ErrorCode_FailedToOpenDynamicLibrary: Unable to open requested dynamic library.
  52. // - Baselib_ErrorCode_NotSupported: This feature is not supported on the current platform.
  53. BASELIB_API Baselib_DynamicLibrary_Handle Baselib_DynamicLibrary_OpenUtf8(
  54. const char* pathnameUtf8,
  55. Baselib_ErrorState* errorState
  56. );
  57. // Open a dynamic library.
  58. // Functionally identical to Baselib_DynamicLibrary_OpenUtf8, but accepts UTF-16 path instead.
  59. BASELIB_API Baselib_DynamicLibrary_Handle Baselib_DynamicLibrary_OpenUtf16(
  60. const baselib_char16_t* pathnameUtf16,
  61. Baselib_ErrorState* errorState
  62. );
  63. // Return a handle that can be used to query functions in the program's scope.
  64. // Must be closed via Baselib_DynamicLibrary_Close.
  65. //
  66. // Possible error codes:
  67. // - Baselib_ErrorCode_NotSupported: This feature is not supported on the current platform.
  68. BASELIB_API Baselib_DynamicLibrary_Handle Baselib_DynamicLibrary_OpenProgramHandle(
  69. Baselib_ErrorState* errorState
  70. );
  71. // Convert native handle into baselib handle without changing the dynamic library ref counter.
  72. //
  73. // Provided handle should be closed either via Baselib_DynamicLibrary_Close or other means.
  74. // The caller is responsible for closing the handle once done with it.
  75. // Other corresponding resources should be closed by other means.
  76. //
  77. // \param handle Platform defined native handle.
  78. // \param type Platform defined native handle type from Baselib_DynamicLibrary_NativeHandleType enum.
  79. // If unsupported type is passed, will return Baselib_DynamicLibrary_Handle_Invalid.
  80. //
  81. // \returns Baselib_DynamicLibrary_Handle handle.
  82. BASELIB_API Baselib_DynamicLibrary_Handle Baselib_DynamicLibrary_FromNativeHandle(
  83. uint64_t handle,
  84. uint32_t type,
  85. Baselib_ErrorState* errorState
  86. );
  87. // Lookup a function in a dynamic library.
  88. //
  89. // \param handle Library handle.
  90. // If Baselib_DynamicLibrary_Handle_Invalid is passed, Baselib_ErrorCode_InvalidArgument will be risen.
  91. // \param functionName Function name to look for.
  92. // If nullptr is passed, Baselib_ErrorCode_InvalidArgument will be risen.
  93. //
  94. // \returns pointer to the function (can be NULL for symbols mapped to NULL).
  95. //
  96. // Possible error codes:
  97. // - Baselib_ErrorCode_FunctionNotFound: Requested function was not found.
  98. BASELIB_API void* Baselib_DynamicLibrary_GetFunction(
  99. Baselib_DynamicLibrary_Handle handle,
  100. const char* functionName,
  101. Baselib_ErrorState* errorState
  102. );
  103. // Close a dynamic library.
  104. //
  105. // Decreases reference counter, if it becomes zero, closes the library.
  106. // If system api will return an error during this operation, the process will be aborted.
  107. //
  108. // \param handle Library handle.
  109. // If Baselib_DynamicLibrary_Handle_Invalid is passed, function is no-op.
  110. BASELIB_API void Baselib_DynamicLibrary_Close(
  111. Baselib_DynamicLibrary_Handle handle
  112. );
  113. #if __cplusplus
  114. }
  115. #endif