#include "plugin_loader.h" #include #include #ifdef _WIN32 #include #else #include #endif namespace rk3588 { namespace { void* LoadLibraryHandle(const std::string& path, std::string& err) { #ifdef _WIN32 HMODULE handle = LoadLibraryA(path.c_str()); if (!handle) { err = "LoadLibrary failed for " + path; } return handle; #else void* handle = dlopen(path.c_str(), RTLD_LAZY); if (!handle) { const char* dl_err = dlerror(); err = dl_err ? dl_err : "dlopen failed"; } return handle; #endif } void CloseLibraryHandle(void* handle) { if (!handle) return; #ifdef _WIN32 FreeLibrary(static_cast(handle)); #else dlclose(handle); #endif } void* LoadSymbol(void* handle, const char* name) { #ifdef _WIN32 return reinterpret_cast(GetProcAddress(static_cast(handle), name)); #else return dlsym(handle, name); #endif } std::string SharedLibExtension() { #ifdef _WIN32 return ".dll"; #elif __APPLE__ return ".dylib"; #else return ".so"; #endif } } // namespace PluginLoader::PluginLoader(std::string plugin_dir) : plugin_dir_(std::move(plugin_dir)) {} PluginLoader::~PluginLoader() { for (auto& kv : cache_) { CloseLibraryHandle(kv.second.handle); } } std::string PluginLoader::BuildLibraryPath(const std::string& type) const { #ifdef _WIN32 return plugin_dir_ + "/" + type + SharedLibExtension(); #else return plugin_dir_ + "/lib" + type + SharedLibExtension(); #endif } bool PluginLoader::LoadPlugin(const std::string& type, PluginHandle& out, std::string& err) { std::string path = BuildLibraryPath(type); void* handle = LoadLibraryHandle(path, err); if (!handle) return false; auto create = reinterpret_cast(LoadSymbol(handle, "CreateNode")); auto get_type = reinterpret_cast(LoadSymbol(handle, "GetNodeType")); auto get_abi = reinterpret_cast(LoadSymbol(handle, "GetAbiVersion")); if (!create || !get_type || !get_abi) { err = "Missing required symbols in plugin: " + path; CloseLibraryHandle(handle); return false; } if (get_abi() != kNodeAbiVersion) { std::ostringstream oss; oss << "ABI mismatch for plugin " << type << ": expected " << kNodeAbiVersion << " got " << get_abi(); err = oss.str(); CloseLibraryHandle(handle); return false; } out.handle = handle; out.create = create; out.get_type = get_type; out.get_abi = get_abi; return true; } std::unique_ptr PluginLoader::Create(const std::string& type, std::string& err) { auto it = cache_.find(type); if (it == cache_.end()) { PluginHandle handle; if (!LoadPlugin(type, handle, err)) { std::cerr << "[PluginLoader] Failed to load plugin '" << type << "': " << err << "\n"; return nullptr; } it = cache_.emplace(type, std::move(handle)).first; } PluginHandle& handle = it->second; std::unique_ptr node(handle.create()); if (!node) { err = "CreateNode returned null for type " + type; return nullptr; } return node; } } // namespace rk3588