// ============================================================================ // ANSLibsLoader.cpp — Master orchestrator for all dynamic library loading // // Coordinates sub-loaders in the correct dependency order: // 1. DLL search path injection (shared directory) // 2. OpenCV (CvLoader) — pre-loads opencv_world + companions // 3. OpenVINO (OvLoader) — pre-loads TBB + openvino.dll // 4. NVIDIA stack (NvDynLoader) — TRT, cuDNN, CUDA // 5. ONNX Runtime (EPLoader) — with execution provider selection // // Shutdown releases everything in reverse order. // ============================================================================ #include "ANSLibsLoader.h" #include "DynLibUtils.h" #include "CvLoader.h" #include "OvLoader.h" #include "NvDynLoader.h" #include "EPLoader.h" #include #include namespace ANSCENTER { // ───────────────────────────────────────────────────────────────────────────── // Static member definitions // ───────────────────────────────────────────────────────────────────────────── bool ANSLibsLoader::s_initialized = false; static std::mutex g_masterMutex; // ───────────────────────────────────────────────────────────────────────────── // Initialize // ───────────────────────────────────────────────────────────────────────────── void ANSLibsLoader::Initialize(const std::string& shared_dir, EngineType preferred) { std::lock_guard lock(g_masterMutex); if (s_initialized) return; std::cout << "==========================================================\n" << "ANSLibsLoader: Initializing all dynamic libraries...\n" << " Shared dir : " << shared_dir << "\n" << " Engine pref : " << static_cast(preferred) << "\n" << "==========================================================" << std::endl; // ── STEP 1: Inject shared dir into search path ─────────────────────────── // This must happen before any DLL loading so all libraries in the shared // directory are discoverable. DynLib::InjectDllSearchPath(shared_dir); // ── STEP 2: Pre-load OpenCV ────────────────────────────────────────────── // Must happen before consuming DLLs (ANSODEngine etc.) are loaded, because // those are import-linked against opencv_world and need the DLL available. CvLoader::Initialize(shared_dir); // ── STEP 3: Pre-load OpenVINO + TBB ────────────────────────────────────── // OpenVINO is used directly (ov::Core) by many projects (ANSODEngine, // ANSLPR, ANSFR, etc.). Pre-loading ensures the DLLs from the shared // directory are resolved before any import-linked consumer is loaded. OvLoader::Initialize(shared_dir); // ── STEP 4: Load NVIDIA stack ──────────────────────────────────────────── // Only attempt if the preferred engine is NVIDIA or AUTO_DETECT. if (preferred == EngineType::NVIDIA_GPU || preferred == EngineType::AUTO_DETECT) { NvDynLoader::Initialize(); } // ── STEP 5: Load ONNX Runtime + select execution provider ──────────────── EPLoader::Initialize(shared_dir, preferred); s_initialized = true; std::cout << "==========================================================\n" << "ANSLibsLoader: Initialization complete.\n" << "==========================================================" << std::endl; } // ───────────────────────────────────────────────────────────────────────────── // Shutdown // ───────────────────────────────────────────────────────────────────────────── void ANSLibsLoader::Shutdown() { std::lock_guard lock(g_masterMutex); // Shut down in reverse initialization order. // Each sub-loader is idempotent and safe to call even if not initialized. EPLoader::Shutdown(); NvDynLoader::Shutdown(); OvLoader::Shutdown(); CvLoader::Shutdown(); s_initialized = false; } // ───────────────────────────────────────────────────────────────────────────── // IsInitialized // ───────────────────────────────────────────────────────────────────────────── bool ANSLibsLoader::IsInitialized() { return s_initialized; } } // namespace ANSCENTER