|
|
@@ -0,0 +1,106 @@
|
|
|
+// Copyright 2019 Dolphin Emulator Project
|
|
|
+// Licensed under GPLv2+
|
|
|
+// Refer to the license.txt file included.
|
|
|
+
|
|
|
+#include <cstring>
|
|
|
+#include <string>
|
|
|
+#include <utility>
|
|
|
+
|
|
|
+#include <fmt/format.h>
|
|
|
+
|
|
|
+#include "common/dynamic_library.h"
|
|
|
+
|
|
|
+#ifdef _WIN32
|
|
|
+#include <windows.h>
|
|
|
+#else
|
|
|
+#include <dlfcn.h>
|
|
|
+#endif
|
|
|
+
|
|
|
+namespace Common {
|
|
|
+
|
|
|
+DynamicLibrary::DynamicLibrary() = default;
|
|
|
+
|
|
|
+DynamicLibrary::DynamicLibrary(const char* filename) {
|
|
|
+ Open(filename);
|
|
|
+}
|
|
|
+
|
|
|
+DynamicLibrary::DynamicLibrary(DynamicLibrary&& rhs) noexcept
|
|
|
+ : handle{std::exchange(rhs.handle, nullptr)} {}
|
|
|
+
|
|
|
+DynamicLibrary& DynamicLibrary::operator=(DynamicLibrary&& rhs) noexcept {
|
|
|
+ Close();
|
|
|
+ handle = std::exchange(rhs.handle, nullptr);
|
|
|
+ return *this;
|
|
|
+}
|
|
|
+
|
|
|
+DynamicLibrary::~DynamicLibrary() {
|
|
|
+ Close();
|
|
|
+}
|
|
|
+
|
|
|
+std::string DynamicLibrary::GetUnprefixedFilename(const char* filename) {
|
|
|
+#if defined(_WIN32)
|
|
|
+ return std::string(filename) + ".dll";
|
|
|
+#elif defined(__APPLE__)
|
|
|
+ return std::string(filename) + ".dylib";
|
|
|
+#else
|
|
|
+ return std::string(filename) + ".so";
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+std::string DynamicLibrary::GetVersionedFilename(const char* libname, int major, int minor) {
|
|
|
+#if defined(_WIN32)
|
|
|
+ if (major >= 0 && minor >= 0)
|
|
|
+ return fmt::format("{}-{}-{}.dll", libname, major, minor);
|
|
|
+ else if (major >= 0)
|
|
|
+ return fmt::format("{}-{}.dll", libname, major);
|
|
|
+ else
|
|
|
+ return fmt::format("{}.dll", libname);
|
|
|
+#elif defined(__APPLE__)
|
|
|
+ const char* prefix = std::strncmp(libname, "lib", 3) ? "lib" : "";
|
|
|
+ if (major >= 0 && minor >= 0)
|
|
|
+ return fmt::format("{}{}.{}.{}.dylib", prefix, libname, major, minor);
|
|
|
+ else if (major >= 0)
|
|
|
+ return fmt::format("{}{}.{}.dylib", prefix, libname, major);
|
|
|
+ else
|
|
|
+ return fmt::format("{}{}.dylib", prefix, libname);
|
|
|
+#else
|
|
|
+ const char* prefix = std::strncmp(libname, "lib", 3) ? "lib" : "";
|
|
|
+ if (major >= 0 && minor >= 0)
|
|
|
+ return fmt::format("{}{}.so.{}.{}", prefix, libname, major, minor);
|
|
|
+ else if (major >= 0)
|
|
|
+ return fmt::format("{}{}.so.{}", prefix, libname, major);
|
|
|
+ else
|
|
|
+ return fmt::format("{}{}.so", prefix, libname);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+bool DynamicLibrary::Open(const char* filename) {
|
|
|
+#ifdef _WIN32
|
|
|
+ handle = reinterpret_cast<void*>(LoadLibraryA(filename));
|
|
|
+#else
|
|
|
+ handle = dlopen(filename, RTLD_NOW);
|
|
|
+#endif
|
|
|
+ return handle != nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+void DynamicLibrary::Close() {
|
|
|
+ if (!IsOpen())
|
|
|
+ return;
|
|
|
+
|
|
|
+#ifdef _WIN32
|
|
|
+ FreeLibrary(reinterpret_cast<HMODULE>(handle));
|
|
|
+#else
|
|
|
+ dlclose(handle);
|
|
|
+#endif
|
|
|
+ handle = nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+void* DynamicLibrary::GetSymbolAddress(const char* name) const {
|
|
|
+#ifdef _WIN32
|
|
|
+ return reinterpret_cast<void*>(GetProcAddress(reinterpret_cast<HMODULE>(handle), name));
|
|
|
+#else
|
|
|
+ return reinterpret_cast<void*>(dlsym(handle, name));
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+} // namespace Common
|