Path: blob/master/thirdparty/openxr/src/loader/loader_platform.hpp
9917 views
// Copyright (c) 2017-2025 The Khronos Group Inc.1// Copyright (c) 2017-2019 Valve Corporation2// Copyright (c) 2017-2019 LunarG, Inc.3//4// SPDX-License-Identifier: Apache-2.0 OR MIT5//6// Initial Authors: Mark Young <[email protected]>, Dave Houlton <[email protected]>7//89#pragma once1011#include <cassert>12#include <sstream>13#include <string>1415#include "xr_dependencies.h"16#include "platform_utils.hpp"1718#if defined(__GNUC__) && __GNUC__ >= 419#define LOADER_EXPORT __attribute__((visibility("default")))20#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)21#define LOADER_EXPORT __attribute__((visibility("default")))22#else23#define LOADER_EXPORT24#endif2526// Environment variables27#if defined(XR_OS_LINUX) || defined(XR_OS_APPLE) || defined(XR_OS_ANDROID)2829#include <sys/types.h>30#include <sys/stat.h>31#include <dlfcn.h>32#include <unistd.h>33#include <stdlib.h>34#include <dirent.h>3536#ifndef PATH_MAX37#define PATH_MAX 102438#endif3940#define PATH_SEPARATOR ':'41#define DIRECTORY_SYMBOL '/'4243// Dynamic Loading of libraries:44typedef void *LoaderPlatformLibraryHandle;45static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {46// When loading the library, we use RTLD_LAZY so that not all symbols have to be47// resolved at this time (which improves performance). Note that if not all symbols48// can be resolved, this could cause crashes later.49// For experimenting/debugging: Define the LD_BIND_NOW environment variable to force all50// symbols to be resolved here.51return dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);52}5354static inline const char *LoaderPlatformLibraryOpenError(const std::string &path) {55(void)path;56return dlerror();57}5859static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) { dlclose(library); }6061static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {62assert(library);63assert(!name.empty());64return dlsym(library, name.c_str());65}6667static inline const char *LoaderPlatformLibraryGetProcAddrError(const std::string &name) {68(void)name;69return dlerror();70}7172#elif defined(XR_OS_WINDOWS)7374#define PATH_SEPARATOR ';'75#define DIRECTORY_SYMBOL '\\'7677// Workaround for MS VS 2010/2013 missing snprintf and vsnprintf78#if defined(_MSC_VER) && _MSC_VER < 190079#include <stdint.h>8081static inline int32_t xr_vsnprintf(char *result_buffer, size_t buffer_size, const char *print_format, va_list varying_list) {82int32_t copy_count = -1;83if (buffer_size != 0) {84copy_count = _vsnprintf_s(result_buffer, buffer_size, _TRUNCATE, print_format, varying_list);85}86if (copy_count == -1) {87copy_count = _vscprintf(print_format, varying_list);88}89return copy_count;90}9192static inline int32_t xr_snprintf(char *result_buffer, size_t buffer_size, const char *print_format, ...) {93va_list varying_list;94va_start(varying_list, print_format);95int32_t copy_count = xr_vsnprintf(result_buffer, buffer_size, print_format, varying_list);96va_end(varying_list);97return copy_count;98}99100#define snprintf xr_snprintf101#define vsnprintf xr_vsnprintf102103#endif104105static inline std::string DescribeError(uint32_t code, bool prefixErrorCode = true) {106std::string str;107108if (prefixErrorCode) {109char prefixBuffer[64];110snprintf(prefixBuffer, sizeof(prefixBuffer), "0x%llx (%lld): ", (uint64_t)code, (int64_t)code);111str = prefixBuffer;112}113114// Could use FORMAT_MESSAGE_FROM_HMODULE to specify an error source.115WCHAR errorBufferW[1024]{};116const DWORD errorBufferWCapacity = sizeof(errorBufferW) / sizeof(errorBufferW[0]);117const DWORD length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, (DWORD)code,118MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorBufferW, errorBufferWCapacity, nullptr);119120if (length) { // If errorBufferW contains what we are looking for...121str += wide_to_utf8(errorBufferW);122} else {123str = "(unknown)";124}125126return str;127}128129// Dynamic Loading:130typedef HMODULE LoaderPlatformLibraryHandle;131static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {132const std::wstring pathW = utf8_to_wide(path);133134// Try loading the library the original way first.135LoaderPlatformLibraryHandle handle = LoadLibraryW(pathW.c_str());136137if (handle == NULL && GetLastError() == ERROR_MOD_NOT_FOUND) {138const DWORD dwAttrib = GetFileAttributesW(pathW.c_str());139const bool fileExists = (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));140if (fileExists) {141// If that failed, then try loading it with broader search folders.142handle = LoadLibraryExW(pathW.c_str(), NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);143}144}145146return handle;147}148149static inline std::string LoaderPlatformLibraryOpenError(const std::string &path) {150std::stringstream ss;151const DWORD dwLastError = GetLastError();152const std::string strError = DescribeError(dwLastError);153ss << "Failed to open dynamic library " << path << " with error " << dwLastError << ": " << strError;154return ss.str();155}156157static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) { FreeLibrary(library); }158159static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {160assert(library);161assert(name.size() > 0);162return reinterpret_cast<void *>(GetProcAddress(library, name.c_str()));163}164165static inline std::string LoaderPlatformLibraryGetProcAddrAddrError(const std::string &name) {166std::stringstream ss;167ss << "Failed to find function " << name << " in dynamic library";168return ss.str();169}170171#else // Not Linux or Windows172173#define PATH_SEPARATOR ':'174#define DIRECTORY_SYMBOL '/'175176static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {177// Stub func178#error("Unknown platform, undefined dynamic library routines resulting");179(void)path;180}181182static inline const char *LoaderPlatformLibraryOpenError(const std::string &path) {183// Stub func184(void)path;185}186187static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) {188// Stub func189(void)library;190}191192static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {193// Stub func194void(library);195void(name);196}197198static inline const char *LoaderPlatformLibraryGetProcAddrError(const std::string &name) {199// Stub func200(void)name;201}202203#endif204205206