Lingfeng Yang | c02cb03 | 2020-10-26 14:21:25 -0700 | [diff] [blame] | 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 | #ifdef _MSC_VER |
| 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 { |
Kaiyi Li | ec3396f | 2022-03-08 13:10:51 -0800 | [diff] [blame] | 54 | private: |
Lingfeng Yang | c02cb03 | 2020-10-26 14:21:25 -0700 | [diff] [blame] | 55 | struct Deleter { |
| 56 | void operator()(SharedLibrary* lib) const { delete lib; } |
| 57 | }; |
| 58 | |
Kaiyi Li | ec3396f | 2022-03-08 13:10:51 -0800 | [diff] [blame] | 59 | public: |
Lingfeng Yang | c02cb03 | 2020-10-26 14:21:25 -0700 | [diff] [blame] | 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. |
Kaiyi Li | ec3396f | 2022-03-08 13:10:51 -0800 | [diff] [blame] | 98 | virtual FunctionPtr findSymbol(const char* symbolName) const; |
Lingfeng Yang | c02cb03 | 2020-10-26 14:21:25 -0700 | [diff] [blame] | 99 | |
Kaiyi Li | ec3396f | 2022-03-08 13:10:51 -0800 | [diff] [blame] | 100 | protected: |
Lingfeng Yang | c02cb03 | 2020-10-26 14:21:25 -0700 | [diff] [blame] | 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. |
Kaiyi Li | ec3396f | 2022-03-08 13:10:51 -0800 | [diff] [blame] | 112 | virtual ~SharedLibrary(); |
Lingfeng Yang | c02cb03 | 2020-10-26 14:21:25 -0700 | [diff] [blame] | 113 | |
Kaiyi Li | ec3396f | 2022-03-08 13:10:51 -0800 | [diff] [blame] | 114 | private: |
| 115 | static SharedLibrary* do_open(const char* libraryName, char* error, size_t errorSize); |
Lingfeng Yang | c02cb03 | 2020-10-26 14:21:25 -0700 | [diff] [blame] | 116 | |
| 117 | HandleType mLib; |
| 118 | }; |
| 119 | |
| 120 | # define EMUGL_LIBNAME(name) "lib" name |
| 121 | |
| 122 | } // namespace base |
| 123 | } // namespace android |
| 124 | |
Kaiyi Li | 1f6758c | 2021-02-07 10:26:13 -0800 | [diff] [blame] | 125 | #undef EMUGL_COMMON_API |
Lingfeng Yang | c02cb03 | 2020-10-26 14:21:25 -0700 | [diff] [blame] | 126 | #endif // EMUGL_COMMON_SHARED_LIBRARY_H |