Add debug and log functions to ANSLIB
This commit is contained in:
@@ -1,31 +1,61 @@
|
||||
#include "ANSLIB.h"
|
||||
#include "ANSLibsLoader.h"
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#define LOAD_FUNC(name) \
|
||||
name##Func = (name##FuncT)GetProcAddress(dllHandle, #name); \
|
||||
if (!name##Func) { success = false; }
|
||||
namespace ANSCENTER
|
||||
{
|
||||
ANSLIB::ANSLIB() {
|
||||
namespace {
|
||||
// Function-pointer typedefs for the ANSLicensingSystem C-facade exports.
|
||||
// Resolved exactly once during PreloadSharedDllsOnce(); after that the
|
||||
// pointers are write-once globals — concurrent reads are race-free.
|
||||
using ANSLogger_LogFnT = void(*)(const char*, const char*, const char*, int);
|
||||
using ANSCENTER_IsDbgEnFnT = int (*)(void);
|
||||
ANSLogger_LogFnT g_ANSLogger_LogInfo = nullptr;
|
||||
ANSLogger_LogFnT g_ANSLogger_LogError = nullptr;
|
||||
ANSLogger_LogFnT g_ANSLogger_LogFatal = nullptr;
|
||||
ANSCENTER_IsDbgEnFnT g_ANSCENTER_IsDebugViewEnabled = nullptr;
|
||||
|
||||
// Pre-load all ANSCORE DLLs from the Shared folder using full paths.
|
||||
// This ensures the correct versions are loaded regardless of PATH order
|
||||
// (e.g., DLHUB_Runtime_Engine may contain older copies on some machines).
|
||||
// Once loaded, Windows reuses them for all subsequent implicit dependencies.
|
||||
const char* sharedDir = "C:\\ProgramData\\ANSCENTER\\Shared\\";
|
||||
const char* preloadDlls[] = {
|
||||
"ANSLicensingSystem.dll",
|
||||
"anslicensing.dll",
|
||||
"ANSMOT.dll",
|
||||
"ANSODEngine.dll",
|
||||
nullptr
|
||||
};
|
||||
for (int i = 0; preloadDlls[i] != nullptr; i++) {
|
||||
std::string fullPath = std::string(sharedDir) + preloadDlls[i];
|
||||
LoadLibraryA(fullPath.c_str());
|
||||
}
|
||||
// Run exactly once per process so LoadLibrary refcounts don't grow per
|
||||
// ANSLIB instance. The DLLs are intentionally pinned for process lifetime.
|
||||
void PreloadSharedDllsOnce() {
|
||||
static std::once_flag s_preloadFlag;
|
||||
std::call_once(s_preloadFlag, []() {
|
||||
const char* sharedDir = "C:\\ProgramData\\ANSCENTER\\Shared\\";
|
||||
const char* preloadDlls[] = {
|
||||
"ANSLicensingSystem.dll",
|
||||
"anslicensing.dll",
|
||||
"ANSMOT.dll",
|
||||
"ANSODEngine.dll",
|
||||
nullptr
|
||||
};
|
||||
for (int i = 0; preloadDlls[i] != nullptr; i++) {
|
||||
std::string fullPath = std::string(sharedDir) + preloadDlls[i];
|
||||
LoadLibraryA(fullPath.c_str());
|
||||
}
|
||||
// Ensure all shared DLLs (OpenCV, OpenVINO, TRT, ORT) are pre-loaded
|
||||
ANSCENTER::ANSLibsLoader::Initialize();
|
||||
|
||||
// Ensure all shared DLLs (OpenCV, OpenVINO, TRT, ORT) are pre-loaded
|
||||
ANSCENTER::ANSLibsLoader::Initialize();
|
||||
// Resolve logging C-facade symbols from the (now-pinned) licensing DLL.
|
||||
// Use GetModuleHandleA — the DLL is already in this process's module
|
||||
// list courtesy of the LoadLibraryA above, so refcount is unchanged.
|
||||
if (HMODULE lic = GetModuleHandleA("ANSLicensingSystem.dll")) {
|
||||
g_ANSLogger_LogInfo = (ANSLogger_LogFnT) GetProcAddress(lic, "ANSLogger_LogInfo");
|
||||
g_ANSLogger_LogError = (ANSLogger_LogFnT) GetProcAddress(lic, "ANSLogger_LogError");
|
||||
g_ANSLogger_LogFatal = (ANSLogger_LogFnT) GetProcAddress(lic, "ANSLogger_LogFatal");
|
||||
g_ANSCENTER_IsDebugViewEnabled = (ANSCENTER_IsDbgEnFnT)GetProcAddress(lic, "ANSCENTER_IsDebugViewEnabled");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ANSLIB::ANSLIB() {
|
||||
PreloadSharedDllsOnce();
|
||||
|
||||
const char* dllPath = "C:\\ProgramData\\ANSCENTER\\Shared\\ANSODEngine.dll";
|
||||
dllHandle = LoadLibraryA(dllPath);
|
||||
@@ -99,6 +129,10 @@ namespace ANSCENTER
|
||||
return -1;
|
||||
}
|
||||
if (CreateANSODHandle_CSFunc) {
|
||||
if (ANSHandle && ReleaseANSODHandleFunc) {
|
||||
ReleaseANSODHandleFunc(&ANSHandle);
|
||||
ANSHandle = nullptr;
|
||||
}
|
||||
const char* result = CreateANSODHandle_CSFunc(&ANSHandle, licenseKey, modelFilePath, modelFileZipPassword,
|
||||
modelThreshold, modelConfThreshold, modelNMSThreshold,
|
||||
1, modelType, detectionType, loadEngineOnCreation);
|
||||
@@ -118,9 +152,8 @@ namespace ANSCENTER
|
||||
return -1;
|
||||
}
|
||||
if (RunInference_CPPFunc) {
|
||||
auto imagePtr = std::make_unique<cv::Mat>(cvImage);
|
||||
try {
|
||||
cv::Mat* rawPtr = imagePtr.get();
|
||||
cv::Mat* rawPtr = &cvImage;
|
||||
int result = RunInference_CPPFunc(&ANSHandle, &rawPtr, cameraId, detectionResult);
|
||||
return result;
|
||||
}
|
||||
@@ -135,9 +168,8 @@ namespace ANSCENTER
|
||||
return -1;
|
||||
}
|
||||
if (RunInferenceComplete_CPPFunc) {
|
||||
auto imagePtr = std::make_unique<cv::Mat>(cvImage);
|
||||
try {
|
||||
cv::Mat* rawPtr = imagePtr.get();
|
||||
cv::Mat* rawPtr = &cvImage;
|
||||
int result = RunInferenceComplete_CPPFunc(&ANSHandle, &rawPtr, cameraId, activeROIMode,detectionResult);
|
||||
return result;
|
||||
}
|
||||
@@ -193,6 +225,10 @@ namespace ANSCENTER
|
||||
int autoDetectEngine, int modelType, int detectionType, int loadEngineOnCreation, const char* modelFolder,std::string& labelMap)
|
||||
{
|
||||
if (!loaded || !LoadModelFromFolderFunc) return -1;
|
||||
if (ANSHandle && ReleaseANSODHandleFunc) {
|
||||
ReleaseANSODHandleFunc(&ANSHandle);
|
||||
ANSHandle = nullptr;
|
||||
}
|
||||
return LoadModelFromFolderFunc(&ANSHandle, licenseKey, modelName, className,
|
||||
detectionScoreThreshold, modelConfThreshold, modelMNSThreshold,
|
||||
autoDetectEngine, modelType, detectionType, loadEngineOnCreation,modelFolder, labelMap);
|
||||
@@ -241,4 +277,27 @@ namespace ANSCENTER
|
||||
if (!loaded || !SetTrackerParametersFunc) return -1;
|
||||
return SetTrackerParametersFunc(&ANSHandle, trackerParams);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Static logging API. Each call ensures the DLL/symbols are resolved (cheap
|
||||
// after the first call — std::call_once degenerates to an atomic load) then
|
||||
// forwards to the C facade. Null-pointer guard makes missing symbols a
|
||||
// silent no-op rather than a crash.
|
||||
// ------------------------------------------------------------------------
|
||||
int ANSLIB::IsDebugViewEnabled() {
|
||||
PreloadSharedDllsOnce();
|
||||
return g_ANSCENTER_IsDebugViewEnabled ? g_ANSCENTER_IsDebugViewEnabled() : 0;
|
||||
}
|
||||
void ANSLIB::LogInfo(const char* src, const char* msg, const char* file, int line) {
|
||||
PreloadSharedDllsOnce();
|
||||
if (g_ANSLogger_LogInfo) g_ANSLogger_LogInfo(src, msg, file, line);
|
||||
}
|
||||
void ANSLIB::LogError(const char* src, const char* msg, const char* file, int line) {
|
||||
PreloadSharedDllsOnce();
|
||||
if (g_ANSLogger_LogError) g_ANSLogger_LogError(src, msg, file, line);
|
||||
}
|
||||
void ANSLIB::LogFatal(const char* src, const char* msg, const char* file, int line) {
|
||||
PreloadSharedDllsOnce();
|
||||
if (g_ANSLogger_LogFatal) g_ANSLogger_LogFatal(src, msg, file, line);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <windows.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <opencv2/core/cuda.hpp>
|
||||
#include <cstdio>
|
||||
enum DetectionType {
|
||||
CLASSIFICATION = 0,
|
||||
DETECTION = 1,
|
||||
@@ -263,6 +264,10 @@ namespace ANSCENTER {
|
||||
public:
|
||||
ANSLIB();
|
||||
~ANSLIB() noexcept;
|
||||
ANSLIB(const ANSLIB&) = delete;
|
||||
ANSLIB& operator=(const ANSLIB&) = delete;
|
||||
ANSLIB(ANSLIB&&) = delete;
|
||||
ANSLIB& operator=(ANSLIB&&) = delete;
|
||||
[[nodiscard]] static ANSLIB* Create();
|
||||
static void Destroy(ANSLIB* instance);
|
||||
[[nodiscard]] int Initialize(const char* licenseKey,
|
||||
@@ -286,6 +291,20 @@ namespace ANSCENTER {
|
||||
[[nodiscard]] int SetPrompt(const char* text);
|
||||
[[nodiscard]] int SetTracker(int trackerType, int enableTracker);
|
||||
[[nodiscard]] int SetTrackerParameters(const char* trackerParams);
|
||||
|
||||
// Logging — process-wide, thread-safe, no instance required.
|
||||
// Routes to SPDLogger inside ANSLicensingSystem.dll via dynamically-resolved
|
||||
// C exports. Silently no-ops if the DLL or symbols are unavailable.
|
||||
static void LogInfo (const char* src, const char* msg, const char* file = "", int line = 0);
|
||||
static void LogError(const char* src, const char* msg, const char* file = "", int line = 0);
|
||||
static void LogFatal(const char* src, const char* msg, const char* file = "", int line = 0);
|
||||
|
||||
// DebugView gate. Wraps ANSCENTER_IsDebugViewEnabled() — non-zero when
|
||||
// logging should be emitted (env var ANSCENTER_DBGVIEW or sentinel file
|
||||
// C:\ProgramData\ANSCENTER\ansvisdebugview.txt). Cheap on the hot path.
|
||||
// Used by the ANSLIB_DBG macro below; can also be called directly to
|
||||
// gate expensive log-prep work.
|
||||
static int IsDebugViewEnabled();
|
||||
private:
|
||||
HMODULE dllHandle = nullptr;
|
||||
bool loaded = false;
|
||||
@@ -436,4 +455,31 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
// ANSLIB_DBG: DebugView logging macro mirroring ANS_DBG, but the gate function
|
||||
// is dynamic-loaded inside ANSLIB.dll — consumers don't need to link or even
|
||||
// know about ANSLicensingSystem.dll. Output goes to BOTH OutputDebugStringA
|
||||
// (DebugView) and stderr, identical format to ANS_DBG: "[tag] formatted\n".
|
||||
//
|
||||
// Usage: ANSLIB_DBG("MyModule", "value=%d ptr=%p", val, ptr);
|
||||
//
|
||||
// Hot-path cost when gate is OFF: one indirect call (atomic load + branch
|
||||
// inside ANSLicensingSystem). When gate is ON: snprintf to a 1024-byte stack
|
||||
// buffer + OutputDebugStringA + fputs. No heap, no per-call allocation.
|
||||
#ifndef ANSCORE_DEBUGVIEW
|
||||
#define ANSCORE_DEBUGVIEW 1 // 1 = runtime-gated (default), 0 = hard-off (stripped)
|
||||
#endif
|
||||
#if ANSCORE_DEBUGVIEW
|
||||
#define ANSLIB_DBG(tag, fmt, ...) do { \
|
||||
if (::ANSCENTER::ANSLIB::IsDebugViewEnabled()) { \
|
||||
char _ansl_dbg_buf[1024]; \
|
||||
snprintf(_ansl_dbg_buf, sizeof(_ansl_dbg_buf), "[" tag "] " fmt "\n", ##__VA_ARGS__); \
|
||||
OutputDebugStringA(_ansl_dbg_buf); \
|
||||
fputs(_ansl_dbg_buf, stderr); \
|
||||
fflush(stderr); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define ANSLIB_DBG(tag, fmt, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user