Refactor project structure
This commit is contained in:
252
core/ANSLibsLoader/OvLoader.cpp
Normal file
252
core/ANSLibsLoader/OvLoader.cpp
Normal file
@@ -0,0 +1,252 @@
|
||||
// ============================================================================
|
||||
// OvLoader.cpp — OpenVINO DLL discovery and pre-loading
|
||||
//
|
||||
// Loading order (dependency chain):
|
||||
// 1. Intel TBB (tbb12.dll / tbbmalloc.dll) — required by openvino.dll
|
||||
// 2. openvino.dll — core runtime
|
||||
// 3. openvino_c.dll — C API (optional, version query)
|
||||
//
|
||||
// Plugins (openvino_intel_cpu_plugin, openvino_intel_gpu_plugin, etc.) and
|
||||
// frontends (openvino_ir_frontend, openvino_onnx_frontend, etc.) are loaded
|
||||
// on-demand by OpenVINO's internal plugin system. They are discovered
|
||||
// automatically because the shared directory is injected into the DLL
|
||||
// search path by ANSLibsLoader before OvLoader::Initialize() runs.
|
||||
// ============================================================================
|
||||
|
||||
#include "OvLoader.h"
|
||||
#include "DynLibUtils.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
|
||||
using namespace ANSCENTER::DynLib;
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Static member definitions
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
std::mutex OvLoader::s_mutex;
|
||||
bool OvLoader::s_initialized = false;
|
||||
OvInfo OvLoader::s_info;
|
||||
LibHandle OvLoader::s_hTbb = nullptr;
|
||||
LibHandle OvLoader::s_hTbbMalloc = nullptr;
|
||||
LibHandle OvLoader::s_hOvCore = nullptr;
|
||||
LibHandle OvLoader::s_hOvC = nullptr;
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Candidate lists — search ANSCENTER shared dir first, then system PATH
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
std::vector<std::string> OvLoader::TbbCandidates(const std::string& shared_dir)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
// ── Priority 1: ANSCENTER shared directory ────────────────────────────────
|
||||
#ifdef _WIN32
|
||||
v.push_back(JoinPath(shared_dir, "tbb12.dll"));
|
||||
v.push_back(JoinPath(shared_dir, "tbb.dll"));
|
||||
#else
|
||||
v.push_back(JoinPath(shared_dir, "libtbb.so.12"));
|
||||
v.push_back(JoinPath(shared_dir, "libtbb.so.2"));
|
||||
v.push_back(JoinPath(shared_dir, "libtbb.so"));
|
||||
#endif
|
||||
|
||||
// ── Priority 2: System PATH / LD_LIBRARY_PATH ─────────────────────────────
|
||||
#ifdef _WIN32
|
||||
v.push_back("tbb12.dll");
|
||||
v.push_back("tbb.dll");
|
||||
#else
|
||||
v.push_back("libtbb.so.12");
|
||||
v.push_back("libtbb.so.2");
|
||||
v.push_back("libtbb.so");
|
||||
#endif
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
std::vector<std::string> OvLoader::TbbMallocCandidates(const std::string& shared_dir)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
#ifdef _WIN32
|
||||
v.push_back(JoinPath(shared_dir, "tbbmalloc.dll"));
|
||||
v.push_back("tbbmalloc.dll");
|
||||
#else
|
||||
v.push_back(JoinPath(shared_dir, "libtbbmalloc.so.2"));
|
||||
v.push_back(JoinPath(shared_dir, "libtbbmalloc.so"));
|
||||
v.push_back("libtbbmalloc.so.2");
|
||||
v.push_back("libtbbmalloc.so");
|
||||
#endif
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
std::vector<std::string> OvLoader::OvCoreCandidates(const std::string& shared_dir)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
#ifdef _WIN32
|
||||
v.push_back(JoinPath(shared_dir, "openvino.dll"));
|
||||
v.push_back("openvino.dll");
|
||||
#else
|
||||
v.push_back(JoinPath(shared_dir, "libopenvino.so"));
|
||||
v.push_back("libopenvino.so");
|
||||
#endif
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
std::vector<std::string> OvLoader::OvCApiCandidates(const std::string& shared_dir)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
#ifdef _WIN32
|
||||
v.push_back(JoinPath(shared_dir, "openvino_c.dll"));
|
||||
v.push_back("openvino_c.dll");
|
||||
#else
|
||||
v.push_back(JoinPath(shared_dir, "libopenvino_c.so"));
|
||||
v.push_back("libopenvino_c.so");
|
||||
#endif
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Version extraction via OpenVINO C API
|
||||
//
|
||||
// The C API exports ov_get_openvino_version() which fills an ov_version_t
|
||||
// struct with a buildNumber string (e.g. "2024.6.0-17404-4c0f47d2335").
|
||||
// We replicate the struct layout locally to avoid including OpenVINO headers.
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
std::string OvLoader::TryGetVersion(LibHandle hOvC)
|
||||
{
|
||||
if (!hOvC) return {};
|
||||
|
||||
// Replicate the ov_version_t layout from openvino/c/ov_common.h
|
||||
struct ov_version_local {
|
||||
const char* buildNumber;
|
||||
const char* description;
|
||||
};
|
||||
|
||||
using fn_get_version = int (*)(ov_version_local*);
|
||||
using fn_free_version = void (*)(ov_version_local*);
|
||||
|
||||
fn_get_version pfnGet = nullptr;
|
||||
fn_free_version pfnFree = nullptr;
|
||||
|
||||
Bind(hOvC, "ov_get_openvino_version", pfnGet);
|
||||
Bind(hOvC, "ov_version_free", pfnFree);
|
||||
|
||||
if (!pfnGet) return {};
|
||||
|
||||
ov_version_local ver = {};
|
||||
if (pfnGet(&ver) == 0 && ver.buildNumber) {
|
||||
std::string result = ver.buildNumber;
|
||||
if (pfnFree) pfnFree(&ver);
|
||||
return result;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Initialize
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
const OvInfo& OvLoader::Initialize(const std::string& shared_dir, bool verbose)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_mutex);
|
||||
if (s_initialized) return s_info;
|
||||
|
||||
// Clean up any partially-loaded handles from a previous failed attempt
|
||||
if (s_hOvC) { FreeLib(s_hOvC); s_hOvC = nullptr; }
|
||||
if (s_hOvCore) { FreeLib(s_hOvCore); s_hOvCore = nullptr; }
|
||||
if (s_hTbbMalloc) { FreeLib(s_hTbbMalloc); s_hTbbMalloc = nullptr; }
|
||||
if (s_hTbb) { FreeLib(s_hTbb); s_hTbb = nullptr; }
|
||||
|
||||
if (verbose) {
|
||||
std::cout << "==================================================" << std::endl;
|
||||
std::cout << "[OvLoader] Discovering OpenVINO libraries..." << std::endl;
|
||||
std::cout << " Shared dir : " << shared_dir << std::endl;
|
||||
std::cout << "==================================================" << std::endl;
|
||||
}
|
||||
|
||||
// ── STEP 1: Inject shared dir into search path ───────────────────────────
|
||||
// Ensures plugins/frontends are discoverable by OpenVINO's internal loader.
|
||||
InjectDllSearchPath(shared_dir);
|
||||
|
||||
// ── STEP 2: Pre-load Intel TBB (dependency of openvino.dll) ──────────────
|
||||
std::string tbbPath;
|
||||
s_hTbb = FindAndLoad(TbbCandidates(shared_dir), tbbPath, verbose);
|
||||
if (s_hTbb) {
|
||||
if (verbose)
|
||||
std::cout << "[OvLoader] TBB loaded: " << tbbPath << std::endl;
|
||||
} else if (verbose) {
|
||||
std::cout << "[OvLoader] WARNING: TBB not found "
|
||||
<< "(openvino.dll may fail to load)." << std::endl;
|
||||
}
|
||||
|
||||
std::string tbbMallocPath;
|
||||
s_hTbbMalloc = FindAndLoad(TbbMallocCandidates(shared_dir),
|
||||
tbbMallocPath, verbose);
|
||||
if (!s_hTbbMalloc && verbose) {
|
||||
std::cout << "[OvLoader] tbbmalloc not found (optional)." << std::endl;
|
||||
}
|
||||
|
||||
// ── STEP 3: Pre-load openvino.dll (core runtime) ─────────────────────────
|
||||
std::string corePath;
|
||||
s_hOvCore = FindAndLoad(OvCoreCandidates(shared_dir), corePath, verbose);
|
||||
if (s_hOvCore) {
|
||||
s_info.dllPath = corePath;
|
||||
s_info.loaded = true;
|
||||
|
||||
if (verbose)
|
||||
std::cout << "[OvLoader] OpenVINO core loaded: " << corePath
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cout << "[OvLoader] WARNING: openvino.dll not found in "
|
||||
<< shared_dir << " or system PATH." << std::endl;
|
||||
std::cout << "[OvLoader] OpenVINO will rely on import-lib resolution "
|
||||
<< "at load time." << std::endl;
|
||||
}
|
||||
|
||||
// ── STEP 4: Pre-load openvino_c.dll + query version ──────────────────────
|
||||
std::string cApiPath;
|
||||
s_hOvC = FindAndLoad(OvCApiCandidates(shared_dir), cApiPath, verbose);
|
||||
if (s_hOvC) {
|
||||
s_info.version = TryGetVersion(s_hOvC);
|
||||
if (!s_info.version.empty() && verbose) {
|
||||
std::cout << "[OvLoader] OpenVINO version = " << s_info.version
|
||||
<< std::endl;
|
||||
}
|
||||
} else if (verbose) {
|
||||
std::cout << "[OvLoader] openvino_c.dll not found "
|
||||
<< "(version detection skipped)." << std::endl;
|
||||
}
|
||||
|
||||
s_initialized = true;
|
||||
|
||||
if (verbose) {
|
||||
std::cout << "[OvLoader] "
|
||||
<< (s_info.loaded
|
||||
? "initialised successfully."
|
||||
: "WARNING — openvino.dll not pre-loaded.")
|
||||
<< std::endl;
|
||||
std::cout << "==================================================" << std::endl;
|
||||
}
|
||||
return s_info;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Shutdown
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
void OvLoader::Shutdown()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_mutex);
|
||||
|
||||
// Release in reverse load order
|
||||
if (s_hOvC) { FreeLib(s_hOvC); s_hOvC = nullptr; }
|
||||
if (s_hOvCore) { FreeLib(s_hOvCore); s_hOvCore = nullptr; }
|
||||
if (s_hTbbMalloc) { FreeLib(s_hTbbMalloc); s_hTbbMalloc = nullptr; }
|
||||
if (s_hTbb) { FreeLib(s_hTbb); s_hTbb = nullptr; }
|
||||
|
||||
s_info = OvInfo{};
|
||||
s_initialized = false;
|
||||
}
|
||||
Reference in New Issue
Block a user