latebindingsymboltable_linux.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * Copyright (c) 2010 The WebRTC project authors. All Rights Reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #ifndef AUDIO_DEVICE_LATEBINDINGSYMBOLTABLE_LINUX_H_
  11. #define AUDIO_DEVICE_LATEBINDINGSYMBOLTABLE_LINUX_H_
  12. #include <assert.h>
  13. #include <stddef.h> // for NULL
  14. #include <string.h>
  15. #include "rtc_base/constructor_magic.h"
  16. // This file provides macros for creating "symbol table" classes to simplify the
  17. // dynamic loading of symbols from DLLs. Currently the implementation only
  18. // supports Linux and pure C symbols.
  19. // See talk/sound/pulseaudiosymboltable.(h|cc) for an example.
  20. namespace webrtc {
  21. namespace adm_linux {
  22. #ifdef WEBRTC_LINUX
  23. typedef void* DllHandle;
  24. const DllHandle kInvalidDllHandle = NULL;
  25. #else
  26. #error Not implemented
  27. #endif
  28. // These are helpers for use only by the class below.
  29. DllHandle InternalLoadDll(const char dll_name[]);
  30. void InternalUnloadDll(DllHandle handle);
  31. bool InternalLoadSymbols(DllHandle handle,
  32. int num_symbols,
  33. const char* const symbol_names[],
  34. void* symbols[]);
  35. template <int SYMBOL_TABLE_SIZE,
  36. const char kDllName[],
  37. const char* const kSymbolNames[]>
  38. class LateBindingSymbolTable {
  39. public:
  40. LateBindingSymbolTable()
  41. : handle_(kInvalidDllHandle), undefined_symbols_(false) {
  42. memset(symbols_, 0, sizeof(symbols_));
  43. }
  44. ~LateBindingSymbolTable() { Unload(); }
  45. static int NumSymbols() { return SYMBOL_TABLE_SIZE; }
  46. // We do not use this, but we offer it for theoretical convenience.
  47. static const char* GetSymbolName(int index) {
  48. assert(index < NumSymbols());
  49. return kSymbolNames[index];
  50. }
  51. bool IsLoaded() const { return handle_ != kInvalidDllHandle; }
  52. // Loads the DLL and the symbol table. Returns true iff the DLL and symbol
  53. // table loaded successfully.
  54. bool Load() {
  55. if (IsLoaded()) {
  56. return true;
  57. }
  58. if (undefined_symbols_) {
  59. // We do not attempt to load again because repeated attempts are not
  60. // likely to succeed and DLL loading is costly.
  61. return false;
  62. }
  63. handle_ = InternalLoadDll(kDllName);
  64. if (!IsLoaded()) {
  65. return false;
  66. }
  67. if (!InternalLoadSymbols(handle_, NumSymbols(), kSymbolNames, symbols_)) {
  68. undefined_symbols_ = true;
  69. Unload();
  70. return false;
  71. }
  72. return true;
  73. }
  74. void Unload() {
  75. if (!IsLoaded()) {
  76. return;
  77. }
  78. InternalUnloadDll(handle_);
  79. handle_ = kInvalidDllHandle;
  80. memset(symbols_, 0, sizeof(symbols_));
  81. }
  82. // Retrieves the given symbol. NOTE: Recommended to use LATESYM_GET below
  83. // instead of this.
  84. void* GetSymbol(int index) const {
  85. assert(IsLoaded());
  86. assert(index < NumSymbols());
  87. return symbols_[index];
  88. }
  89. private:
  90. DllHandle handle_;
  91. bool undefined_symbols_;
  92. void* symbols_[SYMBOL_TABLE_SIZE];
  93. RTC_DISALLOW_COPY_AND_ASSIGN(LateBindingSymbolTable);
  94. };
  95. // This macro must be invoked in a header to declare a symbol table class.
  96. #define LATE_BINDING_SYMBOL_TABLE_DECLARE_BEGIN(ClassName) enum {
  97. // This macro must be invoked in the header declaration once for each symbol
  98. // (recommended to use an X-Macro to avoid duplication).
  99. // This macro defines an enum with names built from the symbols, which
  100. // essentially creates a hash table in the compiler from symbol names to their
  101. // indices in the symbol table class.
  102. #define LATE_BINDING_SYMBOL_TABLE_DECLARE_ENTRY(ClassName, sym) \
  103. ClassName##_SYMBOL_TABLE_INDEX_##sym,
  104. // This macro completes the header declaration.
  105. #define LATE_BINDING_SYMBOL_TABLE_DECLARE_END(ClassName) \
  106. ClassName##_SYMBOL_TABLE_SIZE \
  107. } \
  108. ; \
  109. \
  110. extern const char ClassName##_kDllName[]; \
  111. extern const char* const \
  112. ClassName##_kSymbolNames[ClassName##_SYMBOL_TABLE_SIZE]; \
  113. \
  114. typedef ::webrtc::adm_linux::LateBindingSymbolTable< \
  115. ClassName##_SYMBOL_TABLE_SIZE, ClassName##_kDllName, \
  116. ClassName##_kSymbolNames> \
  117. ClassName;
  118. // This macro must be invoked in a .cc file to define a previously-declared
  119. // symbol table class.
  120. #define LATE_BINDING_SYMBOL_TABLE_DEFINE_BEGIN(ClassName, dllName) \
  121. const char ClassName##_kDllName[] = dllName; \
  122. const char* const ClassName##_kSymbolNames[ClassName##_SYMBOL_TABLE_SIZE] = {
  123. // This macro must be invoked in the .cc definition once for each symbol
  124. // (recommended to use an X-Macro to avoid duplication).
  125. // This would have to use the mangled name if we were to ever support C++
  126. // symbols.
  127. #define LATE_BINDING_SYMBOL_TABLE_DEFINE_ENTRY(ClassName, sym) #sym,
  128. #define LATE_BINDING_SYMBOL_TABLE_DEFINE_END(ClassName) \
  129. } \
  130. ;
  131. // Index of a given symbol in the given symbol table class.
  132. #define LATESYM_INDEXOF(ClassName, sym) (ClassName##_SYMBOL_TABLE_INDEX_##sym)
  133. // Returns a reference to the given late-binded symbol, with the correct type.
  134. #define LATESYM_GET(ClassName, inst, sym) \
  135. (*reinterpret_cast<__typeof__(&sym)>( \
  136. (inst)->GetSymbol(LATESYM_INDEXOF(ClassName, sym))))
  137. } // namespace adm_linux
  138. } // namespace webrtc
  139. #endif // ADM_LATEBINDINGSYMBOLTABLE_LINUX_H_