3
* Copyright 2004--2010, Google Inc.
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions are met:
8
* 1. Redistributions of source code must retain the above copyright notice,
9
* this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright notice,
11
* this list of conditions and the following disclaimer in the documentation
12
* and/or other materials provided with the distribution.
13
* 3. The name of the author may not be used to endorse or promote products
14
* derived from this software without specific prior written permission.
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
#ifndef TALK_BASE_LATEBINDINGSYMBOLTABLE_H_
29
#define TALK_BASE_LATEBINDINGSYMBOLTABLE_H_
33
#include "talk/base/common.h"
34
#include "talk/base/logging.h"
36
// This file provides macros for creating "symbol table" classes to simplify the
37
// dynamic loading of symbols from DLLs. Currently the implementation only
38
// supports Linux and pure C symbols.
39
// See talk/sound/pulseaudiosymboltable.(h|cc) for an example.
44
typedef void *DllHandle;
46
const DllHandle kInvalidDllHandle = NULL;
48
#error Not implemented
51
// These are helpers for use only by the class below.
52
DllHandle InternalLoadDll(const char dll_name[]);
54
void InternalUnloadDll(DllHandle handle);
56
bool InternalLoadSymbols(DllHandle handle,
58
const char *const symbol_names[],
61
template <int SYMBOL_TABLE_SIZE,
62
const char kDllName[],
63
const char *const kSymbolNames[]>
64
class LateBindingSymbolTable {
66
LateBindingSymbolTable()
67
: handle_(kInvalidDllHandle),
68
undefined_symbols_(false) {
69
memset(symbols_, 0, sizeof(symbols_));
72
~LateBindingSymbolTable() {
76
static int NumSymbols() {
77
return SYMBOL_TABLE_SIZE;
80
// We do not use this, but we offer it for theoretical convenience.
81
static const char *GetSymbolName(int index) {
82
ASSERT(index < NumSymbols());
83
return kSymbolNames[index];
86
bool IsLoaded() const {
87
return handle_ != kInvalidDllHandle;
90
// Loads the DLL and the symbol table. Returns true iff the DLL and symbol
91
// table loaded successfully.
96
if (undefined_symbols_) {
97
// We do not attempt to load again because repeated attempts are not
98
// likely to succeed and DLL loading is costly.
99
LOG(LS_ERROR) << "We know there are undefined symbols";
102
handle_ = InternalLoadDll(kDllName);
106
if (!InternalLoadSymbols(handle_, NumSymbols(), kSymbolNames, symbols_)) {
107
undefined_symbols_ = true;
118
InternalUnloadDll(handle_);
119
handle_ = kInvalidDllHandle;
120
memset(symbols_, 0, sizeof(symbols_));
123
// Retrieves the given symbol. NOTE: Recommended to use LATESYM_GET below
125
void *GetSymbol(int index) const {
127
ASSERT(index < NumSymbols());
128
return symbols_[index];
133
bool undefined_symbols_;
134
void *symbols_[SYMBOL_TABLE_SIZE];
136
DISALLOW_COPY_AND_ASSIGN(LateBindingSymbolTable);
139
// This macro must be invoked in a header to declare a symbol table class.
140
#define LATE_BINDING_SYMBOL_TABLE_DECLARE_BEGIN(ClassName) \
143
// This macro must be invoked in the header declaration once for each symbol
144
// (recommended to use an X-Macro to avoid duplication).
145
// This macro defines an enum with names built from the symbols, which
146
// essentially creates a hash table in the compiler from symbol names to their
147
// indices in the symbol table class.
148
#define LATE_BINDING_SYMBOL_TABLE_DECLARE_ENTRY(ClassName, sym) \
149
ClassName##_SYMBOL_TABLE_INDEX_##sym,
151
// This macro completes the header declaration.
152
#define LATE_BINDING_SYMBOL_TABLE_DECLARE_END(ClassName) \
153
ClassName##_SYMBOL_TABLE_SIZE \
156
extern const char ClassName##_kDllName[]; \
157
extern const char *const \
158
ClassName##_kSymbolNames[ClassName##_SYMBOL_TABLE_SIZE]; \
160
typedef ::talk_base::LateBindingSymbolTable<ClassName##_SYMBOL_TABLE_SIZE, \
161
ClassName##_kDllName, \
162
ClassName##_kSymbolNames> \
165
// This macro must be invoked in a .cc file to define a previously-declared
166
// symbol table class.
167
#define LATE_BINDING_SYMBOL_TABLE_DEFINE_BEGIN(ClassName, dllName) \
168
const char ClassName##_kDllName[] = dllName; \
169
const char *const ClassName##_kSymbolNames[ClassName##_SYMBOL_TABLE_SIZE] = {
171
// This macro must be invoked in the .cc definition once for each symbol
172
// (recommended to use an X-Macro to avoid duplication).
173
// This would have to use the mangled name if we were to ever support C++
175
#define LATE_BINDING_SYMBOL_TABLE_DEFINE_ENTRY(ClassName, sym) \
178
#define LATE_BINDING_SYMBOL_TABLE_DEFINE_END(ClassName) \
181
// Index of a given symbol in the given symbol table class.
182
#define LATESYM_INDEXOF(ClassName, sym) \
183
(ClassName##_SYMBOL_TABLE_INDEX_##sym)
185
// Returns a reference to the given late-binded symbol, with the correct type.
186
#define LATESYM_GET(ClassName, inst, sym) \
187
(*reinterpret_cast<typeof(&sym)>( \
188
(inst)->GetSymbol(LATESYM_INDEXOF(ClassName, sym))))
190
} // namespace talk_base
192
#endif // TALK_BASE_LATEBINDINGSYMBOLTABLE_H_