1 // Copyright (C) 2014 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef EMUGL_COMMON_SHARED_LIBRARY_H
16 #define EMUGL_COMMON_SHARED_LIBRARY_H
17 
18 #include <stddef.h>
19 #include <memory>
20 #include <string>
21 #include <unordered_map>
22 
23 #ifdef _WIN32
24 #include <windows.h>
25 #endif
26 
27 #if defined(_MSC_VER) && !defined(STATIC_EMUGL)
28 # ifdef BUILDING_EMUGL_COMMON_SHARED
29 #  define EMUGL_COMMON_API __declspec(dllexport)
30 # else
31 #  define EMUGL_COMMON_API __declspec(dllimport)
32 #endif
33 #else
34 # define EMUGL_COMMON_API
35 #endif
36 
37 namespace android {
38 namespace base {
39 
40 // A class used to open a platform-specific shared library, and probe
41 // it for symbols. Usage is the following:
42 //
43 //    // Open the library.
44 //    SharedLibrary* library = SharedLibrary::open("libFoo");
45 //    if (!library) {
46 //        ... could not find / open library!
47 //    }
48 //
49 //    //Probe for function symbol.
50 //    FunctionPtr my_func = library->findSymbol("my_func");
51 //
52 //  A shared library will be unloaded on program exit.
53 class EMUGL_COMMON_API SharedLibrary {
54    private:
55     struct Deleter {
operatorDeleter56         void operator()(SharedLibrary* lib) const { delete lib; }
57     };
58 
59    public:
60     typedef std::unordered_map<
61             std::string,
62             std::unique_ptr<SharedLibrary, SharedLibrary::Deleter>>
63             LibraryMap;
64 
65     // Open a given library.  If |libraryName| has no extension, a
66     // platform-appropriate extension is added and that path is opened.
67     // If the |libraryName| has an extension, that form is opened.
68     //
69     // On OSX, some libraries don't include an extension (notably OpenGL)
70     // On OSX we try to open |libraryName| first.  If that doesn't exist,
71     // we try |libraryName|.dylib
72     //
73     // On success, returns a new SharedLibrary instance that must be
74     // deleted by the caller.
75     static SharedLibrary* open(const char* libraryName);
76 
77     // A variant of open() that can report a human-readable error if loading
78     // the library fails. |error| is a caller-provided buffer of |errorSize|
79     // bytes that will be filled with snprintf() and always zero terminated.
80     //
81     // On success, return a new SharedLibrary instance, and do not touch
82     // the content of |error|. On failure, return NULL, and sets the content
83     // of |error|.
84     static SharedLibrary* open(const char* libraryName,
85                                char* error,
86                                size_t errorSize);
87 
88     // Adds an extra path to search for libraries.
89     static void addLibrarySearchPath(const char* path);
90 
91     // Generic function pointer type, for values returned by the
92     // findSymbol() method.
93     typedef void (*FunctionPtr)(void);
94 
95     // Probe a given SharedLibrary instance to find a symbol named
96     // |symbolName| in it. Return its address as a FunctionPtr, or
97     // NULL if the symbol is not found.
98     virtual FunctionPtr findSymbol(const char* symbolName) const;
99 
100    protected:
101 #ifdef _WIN32
102     typedef HMODULE HandleType;
103 #else
104     typedef void* HandleType;
105 #endif
106 
107     // Constructor intentionally hidden.
108     SharedLibrary(HandleType);
109 
110     // Closes an existing SharedLibrary hidden so nobody
111     // starts accidently cleaning up these libraries.
112     virtual ~SharedLibrary();
113 
114    private:
115     static SharedLibrary* do_open(const char* libraryName, char* error, size_t errorSize);
116 
117     HandleType mLib;
118 };
119 
120 #  define EMUGL_LIBNAME(name) "lib" name
121 
122 }  // namespace base
123 }  // namespace android
124 
125 #undef EMUGL_COMMON_API
126 #endif  // EMUGL_COMMON_SHARED_LIBRARY_H
127