Refactor project structure
This commit is contained in:
211
core/ANSLibsLoader/CvLoader.cpp
Normal file
211
core/ANSLibsLoader/CvLoader.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
// ============================================================================
|
||||
// CvLoader.cpp — OpenCV DLL discovery and pre-loading
|
||||
// ============================================================================
|
||||
|
||||
#include "CvLoader.h"
|
||||
#include "DynLibUtils.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
|
||||
using namespace ANSCENTER::DynLib;
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Static member definitions
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
std::mutex CvLoader::s_mutex;
|
||||
bool CvLoader::s_initialized = false;
|
||||
CvInfo CvLoader::s_info;
|
||||
LibHandle CvLoader::s_hCvWorld = nullptr;
|
||||
LibHandle CvLoader::s_hCvImgHash = nullptr;
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Helper — extract version string from version code (e.g. 4130 → "4.13.0")
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
static std::string VersionFromCode(int code)
|
||||
{
|
||||
// OpenCV version encoding: XYZZ where X=major, Y=minor, ZZ=patch
|
||||
// 4130 → major=4, minor=13, patch=0
|
||||
// 4100 → major=4, minor=10, patch=0
|
||||
// 490 → major=4, minor=9, patch=0
|
||||
int major = code / 1000;
|
||||
int minor = (code / 10) % 100;
|
||||
int patch = code % 10;
|
||||
return std::to_string(major) + "." +
|
||||
std::to_string(minor) + "." +
|
||||
std::to_string(patch);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Helper — extract version code from DLL filename
|
||||
// "opencv_world4130.dll" → 4130
|
||||
// "opencv_world4100.dll" → 4100
|
||||
// "libopencv_world.so.413"→ 413 (Linux)
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
static int ExtractVersionCode(const std::string& path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Windows: opencv_world<XYZZ>.dll — digits between "opencv_world" and ".dll"
|
||||
const std::string marker = "opencv_world";
|
||||
size_t pos = path.find(marker);
|
||||
if (pos == std::string::npos) return 0;
|
||||
pos += marker.size();
|
||||
size_t dot = path.find('.', pos);
|
||||
if (dot == std::string::npos) return 0;
|
||||
try { return std::stoi(path.substr(pos, dot - pos)); }
|
||||
catch (...) { return 0; }
|
||||
#else
|
||||
// Linux: libopencv_world.so.<digits>
|
||||
size_t dot = path.find_last_of('.');
|
||||
if (dot == std::string::npos || dot + 1 >= path.size()) return 0;
|
||||
try { return std::stoi(path.substr(dot + 1)); }
|
||||
catch (...) { return 0; }
|
||||
#endif
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Candidate lists — search ANSCENTER shared dir first, then system PATH
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
std::vector<std::string> CvLoader::CvWorldCandidates(const std::string& shared_dir)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
// Versioned candidates, newest first (covers OpenCV 4.5 through 4.20+)
|
||||
// Version codes: 4200, 4190, 4180, ..., 4130, ..., 4100, ..., 450
|
||||
static const int versions[] = {
|
||||
4200, 4190, 4180, 4170, 4160, 4150, 4140, 4130, 4120, 4110, 4100,
|
||||
490, 480, 470, 460, 450
|
||||
};
|
||||
|
||||
// ── Priority 1: ANSCENTER shared directory ────────────────────────────────
|
||||
for (int ver : versions) {
|
||||
#ifdef _WIN32
|
||||
v.push_back(JoinPath(shared_dir,
|
||||
"opencv_world" + std::to_string(ver) + ".dll"));
|
||||
#else
|
||||
v.push_back(JoinPath(shared_dir,
|
||||
"libopencv_world.so." + std::to_string(ver)));
|
||||
#endif
|
||||
}
|
||||
|
||||
// ── Priority 2: System PATH / LD_LIBRARY_PATH ─────────────────────────────
|
||||
for (int ver : versions) {
|
||||
#ifdef _WIN32
|
||||
v.push_back("opencv_world" + std::to_string(ver) + ".dll");
|
||||
#else
|
||||
v.push_back("libopencv_world.so." + std::to_string(ver));
|
||||
#endif
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
std::vector<std::string> CvLoader::CvImgHashCandidates(const std::string& shared_dir)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
static const int versions[] = {
|
||||
4200, 4190, 4180, 4170, 4160, 4150, 4140, 4130, 4120, 4110, 4100,
|
||||
490, 480, 470, 460, 450
|
||||
};
|
||||
|
||||
// ── Priority 1: ANSCENTER shared directory ────────────────────────────────
|
||||
for (int ver : versions) {
|
||||
#ifdef _WIN32
|
||||
v.push_back(JoinPath(shared_dir,
|
||||
"opencv_img_hash" + std::to_string(ver) + ".dll"));
|
||||
#else
|
||||
v.push_back(JoinPath(shared_dir,
|
||||
"libopencv_img_hash.so." + std::to_string(ver)));
|
||||
#endif
|
||||
}
|
||||
|
||||
// ── Priority 2: System PATH / LD_LIBRARY_PATH ─────────────────────────────
|
||||
for (int ver : versions) {
|
||||
#ifdef _WIN32
|
||||
v.push_back("opencv_img_hash" + std::to_string(ver) + ".dll");
|
||||
#else
|
||||
v.push_back("libopencv_img_hash.so." + std::to_string(ver));
|
||||
#endif
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Initialize
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
const CvInfo& CvLoader::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_hCvWorld) { FreeLib(s_hCvWorld); s_hCvWorld = nullptr; }
|
||||
if (s_hCvImgHash) { FreeLib(s_hCvImgHash); s_hCvImgHash = nullptr; }
|
||||
|
||||
if (verbose) {
|
||||
std::cout << "==================================================" << std::endl;
|
||||
std::cout << "[CvLoader] Discovering OpenCV libraries..." << std::endl;
|
||||
std::cout << " Shared dir : " << shared_dir << std::endl;
|
||||
std::cout << "==================================================" << std::endl;
|
||||
}
|
||||
|
||||
// ── STEP 1: Inject shared dir into search path ───────────────────────────
|
||||
// This ensures dependent DLLs (e.g. opencv_videoio_ffmpeg) can also be
|
||||
// found when they are co-located with opencv_world in the shared dir.
|
||||
InjectDllSearchPath(shared_dir);
|
||||
|
||||
// ── STEP 2: Pre-load opencv_world ────────────────────────────────────────
|
||||
std::string worldPath;
|
||||
s_hCvWorld = FindAndLoad(CvWorldCandidates(shared_dir), worldPath, verbose);
|
||||
if (s_hCvWorld) {
|
||||
s_info.dllPath = worldPath;
|
||||
s_info.versionCode = ExtractVersionCode(worldPath);
|
||||
s_info.version = VersionFromCode(s_info.versionCode);
|
||||
s_info.loaded = true;
|
||||
|
||||
if (verbose) {
|
||||
std::cout << "[CvLoader] OpenCV version = " << s_info.version
|
||||
<< " (code " << s_info.versionCode << ")" << std::endl;
|
||||
}
|
||||
} else {
|
||||
std::cout << "[CvLoader] WARNING: No opencv_world DLL found in "
|
||||
<< shared_dir << " or system PATH." << std::endl;
|
||||
std::cout << "[CvLoader] OpenCV will rely on import-lib resolution at load time."
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
// ── STEP 3: Pre-load companion modules ───────────────────────────────────
|
||||
// These are optional — missing is a warning, not a failure.
|
||||
std::string imgHashPath;
|
||||
s_hCvImgHash = FindAndLoad(CvImgHashCandidates(shared_dir), imgHashPath, verbose);
|
||||
if (!s_hCvImgHash && verbose) {
|
||||
std::cout << "[CvLoader] opencv_img_hash not found (optional)." << std::endl;
|
||||
}
|
||||
|
||||
s_initialized = true;
|
||||
|
||||
if (verbose) {
|
||||
std::cout << "[CvLoader] "
|
||||
<< (s_info.loaded ? "initialised successfully." : "WARNING — opencv_world not pre-loaded.")
|
||||
<< std::endl;
|
||||
std::cout << "==================================================" << std::endl;
|
||||
}
|
||||
return s_info;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Shutdown
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
void CvLoader::Shutdown()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_mutex);
|
||||
|
||||
// Release in reverse order
|
||||
if (s_hCvImgHash) { FreeLib(s_hCvImgHash); s_hCvImgHash = nullptr; }
|
||||
if (s_hCvWorld) { FreeLib(s_hCvWorld); s_hCvWorld = nullptr; }
|
||||
|
||||
s_info = CvInfo{};
|
||||
s_initialized = false;
|
||||
}
|
||||
Reference in New Issue
Block a user