2 * Copyright (c) 2010 The WebRTC project authors. All Rights Reserved.
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.
11 #ifndef WEBRTC_AUDIO_DEVICE_LATEBINDINGSYMBOLTABLE_LINUX_H
12 #define WEBRTC_AUDIO_DEVICE_LATEBINDINGSYMBOLTABLE_LINUX_H
15 #include <stddef.h> // for NULL
18 #include "webrtc/base/constructormagic.h"
19 #include "webrtc/system_wrappers/interface/trace.h"
21 // This file provides macros for creating "symbol table" classes to simplify the
22 // dynamic loading of symbols from DLLs. Currently the implementation only
23 // supports Linux and pure C symbols.
24 // See talk/sound/pulseaudiosymboltable.(h|cc) for an example.
26 namespace webrtc_adm_linux {
29 typedef void *DllHandle;
31 const DllHandle kInvalidDllHandle = NULL;
33 #error Not implemented
36 // These are helpers for use only by the class below.
37 DllHandle InternalLoadDll(const char dll_name[]);
39 void InternalUnloadDll(DllHandle handle);
41 bool InternalLoadSymbols(DllHandle handle,
43 const char *const symbol_names[],
46 template <int SYMBOL_TABLE_SIZE,
47 const char kDllName[],
48 const char *const kSymbolNames[]>
49 class LateBindingSymbolTable {
51 LateBindingSymbolTable()
52 : handle_(kInvalidDllHandle),
53 undefined_symbols_(false) {
54 memset(symbols_, 0, sizeof(symbols_));
57 ~LateBindingSymbolTable() {
61 static int NumSymbols() {
62 return SYMBOL_TABLE_SIZE;
65 // We do not use this, but we offer it for theoretical convenience.
66 static const char *GetSymbolName(int index) {
67 assert(index < NumSymbols());
68 return kSymbolNames[index];
71 bool IsLoaded() const {
72 return handle_ != kInvalidDllHandle;
75 // Loads the DLL and the symbol table. Returns true iff the DLL and symbol
76 // table loaded successfully.
81 if (undefined_symbols_) {
82 // We do not attempt to load again because repeated attempts are not
83 // likely to succeed and DLL loading is costly.
84 //WEBRTC_TRACE(kTraceError, kTraceAudioDevice, -1,
85 // "We know there are undefined symbols");
88 handle_ = InternalLoadDll(kDllName);
92 if (!InternalLoadSymbols(handle_, NumSymbols(), kSymbolNames, symbols_)) {
93 undefined_symbols_ = true;
104 InternalUnloadDll(handle_);
105 handle_ = kInvalidDllHandle;
106 memset(symbols_, 0, sizeof(symbols_));
109 // Retrieves the given symbol. NOTE: Recommended to use LATESYM_GET below
111 void *GetSymbol(int index) const {
113 assert(index < NumSymbols());
114 return symbols_[index];
119 bool undefined_symbols_;
120 void *symbols_[SYMBOL_TABLE_SIZE];
122 DISALLOW_COPY_AND_ASSIGN(LateBindingSymbolTable);
125 // This macro must be invoked in a header to declare a symbol table class.
126 #define LATE_BINDING_SYMBOL_TABLE_DECLARE_BEGIN(ClassName) \
129 // This macro must be invoked in the header declaration once for each symbol
130 // (recommended to use an X-Macro to avoid duplication).
131 // This macro defines an enum with names built from the symbols, which
132 // essentially creates a hash table in the compiler from symbol names to their
133 // indices in the symbol table class.
134 #define LATE_BINDING_SYMBOL_TABLE_DECLARE_ENTRY(ClassName, sym) \
135 ClassName##_SYMBOL_TABLE_INDEX_##sym,
137 // This macro completes the header declaration.
138 #define LATE_BINDING_SYMBOL_TABLE_DECLARE_END(ClassName) \
139 ClassName##_SYMBOL_TABLE_SIZE \
142 extern const char ClassName##_kDllName[]; \
143 extern const char *const \
144 ClassName##_kSymbolNames[ClassName##_SYMBOL_TABLE_SIZE]; \
146 typedef ::webrtc_adm_linux::LateBindingSymbolTable<ClassName##_SYMBOL_TABLE_SIZE, \
147 ClassName##_kDllName, \
148 ClassName##_kSymbolNames> \
151 // This macro must be invoked in a .cc file to define a previously-declared
152 // symbol table class.
153 #define LATE_BINDING_SYMBOL_TABLE_DEFINE_BEGIN(ClassName, dllName) \
154 const char ClassName##_kDllName[] = dllName; \
155 const char *const ClassName##_kSymbolNames[ClassName##_SYMBOL_TABLE_SIZE] = {
157 // This macro must be invoked in the .cc definition once for each symbol
158 // (recommended to use an X-Macro to avoid duplication).
159 // This would have to use the mangled name if we were to ever support C++
161 #define LATE_BINDING_SYMBOL_TABLE_DEFINE_ENTRY(ClassName, sym) \
164 #define LATE_BINDING_SYMBOL_TABLE_DEFINE_END(ClassName) \
167 // Index of a given symbol in the given symbol table class.
168 #define LATESYM_INDEXOF(ClassName, sym) \
169 (ClassName##_SYMBOL_TABLE_INDEX_##sym)
171 // Returns a reference to the given late-binded symbol, with the correct type.
172 #define LATESYM_GET(ClassName, inst, sym) \
173 (*reinterpret_cast<typeof(&sym)>( \
174 (inst)->GetSymbol(LATESYM_INDEXOF(ClassName, sym))))
176 } // namespace webrtc_adm_linux
178 #endif // WEBRTC_ADM_LATEBINDINGSYMBOLTABLE_LINUX_H