143 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
 | 
						|
#include "os.hpp"
 | 
						|
 | 
						|
#include <filesystem>
 | 
						|
#include "../debug/assert.hpp"
 | 
						|
 | 
						|
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
 | 
						|
    #include <mutex>
 | 
						|
    #include <dlfcn.h>
 | 
						|
    #include <pthread.h>
 | 
						|
#elif MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
 | 
						|
    #include <array>
 | 
						|
    #include <windows.h>
 | 
						|
    #include "../util/winundef.hpp"
 | 
						|
#endif
 | 
						|
 | 
						|
namespace fs = std::filesystem;
 | 
						|
 | 
						|
namespace mijin
 | 
						|
{
 | 
						|
 | 
						|
//
 | 
						|
// internal defines
 | 
						|
//
 | 
						|
 | 
						|
//
 | 
						|
// internal constants
 | 
						|
//
 | 
						|
 | 
						|
//
 | 
						|
// internal types
 | 
						|
//
 | 
						|
 | 
						|
//
 | 
						|
// internal variables
 | 
						|
//
 | 
						|
 | 
						|
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
 | 
						|
namespace
 | 
						|
{
 | 
						|
std::mutex gDlErrorMutex; // dlerror may not be thread-safe
 | 
						|
}
 | 
						|
#endif // MIJIN_TARGET_OS == MIJIN_OS_LINUX
 | 
						|
 | 
						|
//
 | 
						|
// internal functions
 | 
						|
//
 | 
						|
 | 
						|
//
 | 
						|
// public functions
 | 
						|
//
 | 
						|
 | 
						|
Result<LibraryHandle> openSharedLibrary(std::string_view libraryFile) MIJIN_NOEXCEPT
 | 
						|
{
 | 
						|
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
 | 
						|
    const std::unique_lock dlErrorLock(gDlErrorMutex);
 | 
						|
    dlerror(); // NOLINT(concurrency-mt-unsafe) we take care of that
 | 
						|
 | 
						|
    const fs::path libraryPath = fs::absolute(libraryFile);
 | 
						|
    void* ptr = dlopen(libraryPath.c_str(), RTLD_NOW);
 | 
						|
    if (ptr == nullptr)
 | 
						|
    {
 | 
						|
        return ResultError(dlerror()); // NOLINT(concurrency-mt-unsafe) we take care of that
 | 
						|
    }
 | 
						|
    return LibraryHandle{.data = dlopen(libraryPath.c_str(), RTLD_NOW)};
 | 
						|
#elif MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
 | 
						|
	// TODO
 | 
						|
	(void) libraryFile;
 | 
						|
	return {};
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
bool closeSharedLibrary(const LibraryHandle library) MIJIN_NOEXCEPT
 | 
						|
{
 | 
						|
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
 | 
						|
    return dlclose(library.data) == 0;
 | 
						|
#elif MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
 | 
						|
    (void) library;
 | 
						|
    return true;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void* loadSymbolFromLibrary(const LibraryHandle library, const char* symbolName) MIJIN_NOEXCEPT
 | 
						|
{
 | 
						|
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
 | 
						|
    return dlsym(library.data, symbolName);
 | 
						|
#elif MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
 | 
						|
	(void) library;
 | 
						|
	(void) symbolName;
 | 
						|
	return nullptr;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void setCurrentThreadName(const char* threadName) MIJIN_NOEXCEPT
 | 
						|
{
 | 
						|
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
 | 
						|
    pthread_setname_np(pthread_self(), threadName);
 | 
						|
#elif MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
 | 
						|
	(void) threadName;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
std::string getExecutablePath() MIJIN_NOEXCEPT
 | 
						|
{
 | 
						|
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
 | 
						|
    return fs::canonical("/proc/self/exe").string();
 | 
						|
#elif MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
 | 
						|
    // TODO: this is completely untested
 | 
						|
    std::array<char, 1024> buffer;
 | 
						|
    if (FAILED(GetModuleFileNameA(nullptr, buffer.data(), static_cast<DWORD>(buffer.size()))))
 | 
						|
    {
 | 
						|
        std::vector<char> buffer2;
 | 
						|
        buffer2.resize(1024);
 | 
						|
        do
 | 
						|
        {
 | 
						|
            if (buffer2.size() >= 10240)
 | 
						|
            {
 | 
						|
                MIJIN_ERROR("Something is wrong.");
 | 
						|
                return "";
 | 
						|
            }
 | 
						|
            buffer2.resize(buffer2.size() + 1024);
 | 
						|
        }
 | 
						|
        while (FAILED(GetModuleFileNameA(nullptr, buffer.data(), static_cast<DWORD>(buffer.size()))));
 | 
						|
        return buffer2.data();
 | 
						|
    }
 | 
						|
    return buffer.data();
 | 
						|
#else
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
[[nodiscard]] std::string makeLibraryFilename(std::string_view libraryName) MIJIN_NOEXCEPT
 | 
						|
{
 | 
						|
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
 | 
						|
    return "lib" + std::string(libraryName) + ".so";
 | 
						|
#elif MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
 | 
						|
    return std::string(libraryName) + ".dll";
 | 
						|
#else
 | 
						|
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
} // namespace mijin
 |