diff --git a/gpt4all-backend/CMakeLists.txt b/gpt4all-backend/CMakeLists.txt index dd69e1b7..45745fc4 100644 --- a/gpt4all-backend/CMakeLists.txt +++ b/gpt4all-backend/CMakeLists.txt @@ -149,7 +149,7 @@ endforeach() add_library(llmodel llmodel.h llmodel.cpp llmodel_shared.cpp llmodel_c.h llmodel_c.cpp - dlhandle.h + dlhandle.cpp ) target_compile_definitions(llmodel PRIVATE LIB_FILE_EXT="${CMAKE_SHARED_LIBRARY_SUFFIX}") diff --git a/gpt4all-backend/dlhandle.cpp b/gpt4all-backend/dlhandle.cpp new file mode 100644 index 00000000..f4b99860 --- /dev/null +++ b/gpt4all-backend/dlhandle.cpp @@ -0,0 +1,56 @@ +#include "dlhandle.h" + +#ifndef _WIN32 +# include +#else +# include +# define WIN32_LEAN_AND_MEAN +# ifndef NOMINMAX +# define NOMINMAX +# endif +# include +#endif + +namespace fs = std::filesystem; + + +#ifndef _WIN32 + +Dlhandle::Dlhandle(const fs::path &fpath) { + chandle = dlopen(fpath.c_str(), RTLD_LAZY | RTLD_LOCAL); + if (!chandle) { + throw Exception("dlopen(\"" + fpath.filename().string() + "\"): " + dlerror()); + } +} + +Dlhandle::~Dlhandle() { + if (chandle) dlclose(chandle); +} + +void *Dlhandle::get_internal(const char *symbol) const { + return dlsym(chandle, symbol); +} + +#else // defined(_WIN32) + +Dlhandle::Dlhandle(const fs::path &fpath) { + auto afpath = fs::absolute(fpath); + chandle = LoadLibraryExW(afpath.c_str(), NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR); + + if (!chandle) { + auto err = GetLastError(); + std::ostringstream ss; + ss << "LoadLibraryExW(\"" << fpath.filename().string() << "\") failed with error 0x" << std::hex << err; + throw Exception(ss.str()); + } +} + +Dlhandle::~Dlhandle() { + if (chandle) FreeLibrary(HMODULE(chandle)); +} + +void *Dlhandle::get_internal(const char *symbol) const { + return GetProcAddress(HMODULE(chandle), symbol); +} + +#endif // defined(_WIN32) diff --git a/gpt4all-backend/dlhandle.h b/gpt4all-backend/dlhandle.h index f24a2a25..0629b482 100644 --- a/gpt4all-backend/dlhandle.h +++ b/gpt4all-backend/dlhandle.h @@ -1,74 +1,15 @@ -#ifndef DLHANDLE_H -#define DLHANDLE_H -#ifndef _WIN32 -#include -#include -#include -#include +#pragma once - - -class Dlhandle { - void *chandle; - -public: - class Exception : public std::runtime_error { - public: - using std::runtime_error::runtime_error; - }; - - Dlhandle() : chandle(nullptr) {} - Dlhandle(const std::string& fpath, int flags = RTLD_LAZY | RTLD_LOCAL) { - chandle = dlopen(fpath.c_str(), flags); - if (!chandle) { - throw Exception("dlopen(\""+fpath+"\"): "+dlerror()); - } - } - Dlhandle(const Dlhandle& o) = delete; - Dlhandle(Dlhandle&& o) : chandle(o.chandle) { - o.chandle = nullptr; - } - ~Dlhandle() { - if (chandle) dlclose(chandle); - } - - auto operator =(Dlhandle&& o) { - chandle = std::exchange(o.chandle, nullptr); - } - - bool is_valid() const { - return chandle != nullptr; - } - operator bool() const { - return is_valid(); - } - - template - T* get(const std::string& fname) const { - auto fres = reinterpret_cast(dlsym(chandle, fname.c_str())); - return (dlerror()==NULL)?fres:nullptr; - } - auto get_fnc(const std::string& fname) const { - return get(fname); - } -}; -#else -#include #include -#include -#include #include +#include +#include -#define WIN32_LEAN_AND_MEAN -#ifndef NOMINMAX -# define NOMINMAX -#endif -#include -#include +namespace fs = std::filesystem; class Dlhandle { - HMODULE chandle; + void *chandle = nullptr; public: class Exception : public std::runtime_error { @@ -76,34 +17,31 @@ public: using std::runtime_error::runtime_error; }; - Dlhandle() : chandle(nullptr) {} - Dlhandle(const std::string& fpath) { - std::string afpath = std::filesystem::absolute(fpath).string(); - std::replace(afpath.begin(), afpath.end(), '/', '\\'); - chandle = LoadLibraryExA(afpath.c_str(), NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR); - if (!chandle) { - throw Exception("dlopen(\""+fpath+"\"): Error"); - } - } - Dlhandle(const Dlhandle& o) = delete; - Dlhandle(Dlhandle&& o) : chandle(o.chandle) { + Dlhandle() = default; + Dlhandle(const fs::path &fpath); + Dlhandle(const Dlhandle &o) = delete; + Dlhandle(Dlhandle &&o) + : chandle(o.chandle) + { o.chandle = nullptr; } - ~Dlhandle() { - if (chandle) FreeLibrary(chandle); + + ~Dlhandle(); + + Dlhandle &operator=(Dlhandle &&o) { + chandle = std::exchange(o.chandle, nullptr); + return *this; } - bool is_valid() const { - return chandle != nullptr; + template + T *get(const std::string &symbol) const { + return reinterpret_cast(get_internal(symbol.c_str())); } - template - T* get(const std::string& fname) const { - return reinterpret_cast(GetProcAddress(chandle, fname.c_str())); - } - auto get_fnc(const std::string& fname) const { - return get(fname); + auto get_fnc(const std::string &symbol) const { + return get(symbol); } + +private: + void *get_internal(const char *symbol) const; }; -#endif -#endif // DLHANDLE_H diff --git a/gpt4all-backend/llmodel.cpp b/gpt4all-backend/llmodel.cpp index fa756056..3a340c81 100644 --- a/gpt4all-backend/llmodel.cpp +++ b/gpt4all-backend/llmodel.cpp @@ -1,6 +1,4 @@ #include "llmodel.h" -#include "dlhandle.h" -#include "sysinfo.h" #include #include @@ -15,6 +13,9 @@ #include #include +#include "dlhandle.h" +#include "sysinfo.h" + #ifdef _WIN32 # define WIN32_LEAN_AND_MEAN # ifndef NOMINMAX @@ -27,6 +28,8 @@ # include #endif +namespace fs = std::filesystem; + #ifndef __APPLE__ static const std::string DEFAULT_BACKENDS[] = {"kompute", "cpu"}; #elif defined(__aarch64__) @@ -129,17 +132,17 @@ const std::vector &LLModel::Implementation::implementat std::string path; // Split the paths string by the delimiter and process each path. while (std::getline(ss, path, ';')) { - std::filesystem::path fs_path(path); + std::u8string u8_path(path.begin(), path.end()); // Iterate over all libraries - for (const auto& f : std::filesystem::directory_iterator(fs_path)) { - const std::filesystem::path& p = f.path(); + for (const auto &f : fs::directory_iterator(u8_path)) { + const fs::path &p = f.path(); if (p.extension() != LIB_FILE_EXT) continue; if (!std::regex_search(p.stem().string(), re)) continue; // Add to list if model implementation try { - Dlhandle dl(p.string()); + Dlhandle dl(p); if (!isImplementation(dl)) continue; fres.emplace_back(Implementation(std::move(dl)));