2025-11-27 14:15:20 +08:00
|
|
|
#include "dll_loader.hpp"
|
|
|
|
|
#include <stdexcept>
|
2026-01-04 23:11:58 +08:00
|
|
|
#include <filesystem>
|
|
|
|
|
|
|
|
|
|
#if defined(BASALT_OS_WINDOWS)
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
#else
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#endif
|
2025-11-27 14:15:20 +08:00
|
|
|
|
2026-01-05 16:51:58 +08:00
|
|
|
using ::Basalt::Shared::Char::BSStringView;
|
|
|
|
|
|
2025-11-27 14:15:20 +08:00
|
|
|
namespace Basalt::Presenter {
|
|
|
|
|
|
2026-01-04 23:11:58 +08:00
|
|
|
static std::filesystem::path get_executable() {
|
|
|
|
|
#if defined(BASALT_OS_WINDOWS)
|
|
|
|
|
wchar_t buffer[MAX_PATH];
|
|
|
|
|
DWORD hr = GetModuleFileNameW(NULL, buffer, MAX_PATH);
|
2026-01-05 16:51:58 +08:00
|
|
|
if (hr > 0 && hr < MAX_PATH) {
|
2026-01-04 23:11:58 +08:00
|
|
|
return std::filesystem::path(buffer);
|
2026-01-05 16:51:58 +08:00
|
|
|
} else {
|
|
|
|
|
throw std::runtime_error("Failed to get executable path");
|
2026-01-04 23:11:58 +08:00
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
char buffer[PATH_MAX];
|
|
|
|
|
ssize_t len = readlink("/proc/self/exe", buffer, sizeof(buffer) - 1);
|
|
|
|
|
if (len != -1) {
|
|
|
|
|
buffer[len] = '\0';
|
|
|
|
|
return std::filesystem::path(buffer);
|
|
|
|
|
} else {
|
|
|
|
|
throw std::runtime_error("Failed to get executable path");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-05 16:51:58 +08:00
|
|
|
DllLoader::DllLoader(DllKind kind, const BSStringView& filename) {
|
2026-01-04 23:11:58 +08:00
|
|
|
// Build DLL full path
|
|
|
|
|
auto dll_path = get_executable().parent_path();
|
|
|
|
|
dll_path /= BSTEXT("plugin");
|
|
|
|
|
switch (kind) {
|
|
|
|
|
case DllKind::Engine:
|
|
|
|
|
dll_path /= BSTEXT("engine");
|
|
|
|
|
break;
|
|
|
|
|
case DllKind::Deliver:
|
|
|
|
|
dll_path /= BSTEXT("deliver");
|
|
|
|
|
break;
|
|
|
|
|
case DllKind::ObjectLoader:
|
|
|
|
|
dll_path /= BSTEXT("object_loader");
|
|
|
|
|
break;
|
|
|
|
|
case DllKind::AnimeLoader:
|
|
|
|
|
dll_path /= BSTEXT("anime_loader");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
dll_path /= filename;
|
|
|
|
|
#if defined(BASALT_OS_WINDOWS)
|
|
|
|
|
dll_path.replace_extension(BSTEXT(".dll"));
|
2026-01-06 16:27:19 +08:00
|
|
|
#else
|
|
|
|
|
dll_path.replace_extension(BSTEXT(".so"));
|
2026-01-04 23:11:58 +08:00
|
|
|
#endif
|
|
|
|
|
// Load DLL
|
2025-11-27 14:15:20 +08:00
|
|
|
#if defined(BASALT_OS_WINDOWS)
|
2026-01-04 23:11:58 +08:00
|
|
|
m_Handle = LoadLibraryW(dll_path.wstring().c_str());
|
2025-11-27 14:15:20 +08:00
|
|
|
#else
|
2026-01-04 23:11:58 +08:00
|
|
|
m_Handle = dlopen(dll_path.string().c_str(), RTLD_LAZY);
|
2025-11-27 14:15:20 +08:00
|
|
|
#endif
|
2026-01-04 23:11:58 +08:00
|
|
|
// Check loaded DLL
|
2025-11-27 21:52:40 +08:00
|
|
|
if (!m_Handle) throw std::runtime_error("Can not load given dynamic library.");
|
2025-11-27 14:15:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DllLoader::~DllLoader() {
|
|
|
|
|
if (m_Handle) {
|
|
|
|
|
#if defined(BASALT_OS_WINDOWS)
|
|
|
|
|
FreeLibrary(m_Handle);
|
|
|
|
|
#else
|
|
|
|
|
dlclose(m_Handle);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-27 21:52:40 +08:00
|
|
|
void *DllLoader::GetFunctionPointer(const char *name) {
|
|
|
|
|
if (!m_Handle) throw std::runtime_error("Can not fetch function pointer on not loaded dynamic library.");
|
|
|
|
|
#if defined(BASALT_OS_WINDOWS)
|
|
|
|
|
return (void *) GetProcAddress(m_Handle, name);
|
|
|
|
|
#else
|
|
|
|
|
return (void *) dlsym(m_Handle, name);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-27 14:15:20 +08:00
|
|
|
} // namespace Basalt::Presenter
|