281 lines
7.9 KiB
C++
281 lines
7.9 KiB
C++
// dllmain.cpp : Defines the entry point for the DLL application.
|
|
#include "pch.h"
|
|
#include "ANSMOT.h"
|
|
#include "ANSByteTrackNCNN.h"
|
|
#include "ANSByteTrack.h"
|
|
#include "ANSByteTrackEigen.h"
|
|
#include "ANSOCSortTrack.h"
|
|
#include "ANSUCMC.h"
|
|
#include <unordered_map>
|
|
#include <condition_variable>
|
|
#include <mutex>
|
|
#include <cstdint>
|
|
|
|
// Handle registry with refcount — prevents use-after-free when
|
|
// ReleaseANSMOTHandle is called while an operation is still running.
|
|
static std::unordered_map<ANSCENTER::ANSMOT*, int>& MOTHandleRegistry() {
|
|
static std::unordered_map<ANSCENTER::ANSMOT*, int> s;
|
|
return s;
|
|
}
|
|
static std::mutex& MOTHandleRegistryMutex() {
|
|
static std::mutex m;
|
|
return m;
|
|
}
|
|
static std::condition_variable& MOTHandleRegistryCV() {
|
|
static std::condition_variable cv;
|
|
return cv;
|
|
}
|
|
|
|
static void RegisterMOTHandle(ANSCENTER::ANSMOT* h) {
|
|
std::lock_guard<std::mutex> lk(MOTHandleRegistryMutex());
|
|
MOTHandleRegistry()[h] = 1;
|
|
}
|
|
|
|
static ANSCENTER::ANSMOT* AcquireMOTHandle(ANSCENTER::ANSMOT* h) {
|
|
std::lock_guard<std::mutex> lk(MOTHandleRegistryMutex());
|
|
auto it = MOTHandleRegistry().find(h);
|
|
if (it == MOTHandleRegistry().end()) return nullptr;
|
|
it->second++;
|
|
return h;
|
|
}
|
|
|
|
static bool ReleaseMOTHandleRef(ANSCENTER::ANSMOT* h) {
|
|
std::lock_guard<std::mutex> lk(MOTHandleRegistryMutex());
|
|
auto it = MOTHandleRegistry().find(h);
|
|
if (it == MOTHandleRegistry().end()) return false;
|
|
it->second--;
|
|
if (it->second <= 0) {
|
|
MOTHandleRegistry().erase(it);
|
|
MOTHandleRegistryCV().notify_all();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool UnregisterMOTHandle(ANSCENTER::ANSMOT* h) {
|
|
std::unique_lock<std::mutex> lk(MOTHandleRegistryMutex());
|
|
auto it = MOTHandleRegistry().find(h);
|
|
if (it == MOTHandleRegistry().end()) return false;
|
|
it->second--;
|
|
bool ok = MOTHandleRegistryCV().wait_for(lk, std::chrono::seconds(30), [&]() {
|
|
auto it2 = MOTHandleRegistry().find(h);
|
|
return it2 == MOTHandleRegistry().end() || it2->second <= 0;
|
|
});
|
|
if (!ok) {
|
|
OutputDebugStringA("WARNING: UnregisterMOTHandle timed out waiting for in-flight operations\n");
|
|
}
|
|
MOTHandleRegistry().erase(h);
|
|
return true;
|
|
}
|
|
|
|
// RAII guard — ensures ReleaseMOTHandleRef is always called
|
|
class MOTHandleGuard {
|
|
ANSCENTER::ANSMOT* engine;
|
|
public:
|
|
explicit MOTHandleGuard(ANSCENTER::ANSMOT* e) : engine(e) {}
|
|
~MOTHandleGuard() { if (engine) ReleaseMOTHandleRef(engine); }
|
|
ANSCENTER::ANSMOT* get() const { return engine; }
|
|
explicit operator bool() const { return engine != nullptr; }
|
|
MOTHandleGuard(const MOTHandleGuard&) = delete;
|
|
MOTHandleGuard& operator=(const MOTHandleGuard&) = delete;
|
|
};
|
|
|
|
BOOL APIENTRY DllMain( HMODULE hModule,
|
|
DWORD ul_reason_for_call,
|
|
LPVOID lpReserved
|
|
)
|
|
{
|
|
switch (ul_reason_for_call)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
case DLL_THREAD_ATTACH:
|
|
case DLL_THREAD_DETACH:
|
|
case DLL_PROCESS_DETACH:
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
/*
|
|
enum MOTEType {
|
|
BYTETRACKNCNN = 0,
|
|
BYTETRACK = 1,
|
|
BYTETRACKEIGEN=2,
|
|
OCSORT=3
|
|
};
|
|
*/
|
|
extern "C" __declspec(dllexport) int __cdecl CreateANSMOTHandle(ANSCENTER::ANSMOT **Handle, int motType) {
|
|
if (Handle == nullptr) return 0;
|
|
try {
|
|
// Release existing handle if called twice (prevents leak from LabVIEW)
|
|
if (*Handle) {
|
|
if (UnregisterMOTHandle(*Handle)) {
|
|
(*Handle)->Destroy();
|
|
delete *Handle;
|
|
}
|
|
*Handle = nullptr;
|
|
}
|
|
|
|
switch (motType) {
|
|
case 0: //BYTETRACKNCNN =0
|
|
(*Handle) = new ANSCENTER::ANSByteTrack();// ANSByteTrackNCNN();
|
|
break;
|
|
case 1: //BYTETRACK = 1
|
|
(*Handle) = new ANSCENTER::ANSByteTrack();
|
|
break;
|
|
case 2://BYTETRACKEIGEN = 2
|
|
(*Handle) = new ANSCENTER::ANSByteTrack();// ANSByteTrackEigen();
|
|
break;
|
|
case 3://UCMC = 3
|
|
(*Handle) = new ANSCENTER::ANSUCMCTrack();
|
|
break;
|
|
case 4://OCSORT = 4
|
|
(*Handle) = new ANSCENTER::ANSOCSortTrack();
|
|
break;
|
|
default:
|
|
(*Handle) = new ANSCENTER::ANSByteTrack();// ANSByteTrackNCNN();
|
|
break;
|
|
}
|
|
if (*Handle == nullptr) {
|
|
return 0;
|
|
}
|
|
else {
|
|
RegisterMOTHandle(*Handle);
|
|
return 1;
|
|
}
|
|
}
|
|
catch (std::exception& e) {
|
|
return 0;
|
|
}
|
|
catch (...) {
|
|
return 0;
|
|
}
|
|
}
|
|
static int ReleaseANSMOTHandle_Impl(ANSCENTER::ANSMOT** Handle) {
|
|
try {
|
|
if (!Handle || !*Handle) return 1;
|
|
if (!UnregisterMOTHandle(*Handle)) {
|
|
*Handle = nullptr;
|
|
return 1;
|
|
}
|
|
(*Handle)->Destroy();
|
|
delete *Handle;
|
|
*Handle = nullptr;
|
|
return 1;
|
|
}
|
|
catch (...) {
|
|
if (Handle) *Handle = nullptr;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
extern "C" __declspec(dllexport) int __cdecl ReleaseANSMOTHandle(ANSCENTER::ANSMOT **Handle) {
|
|
__try {
|
|
return ReleaseANSMOTHandle_Impl(Handle);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
|
if (Handle) *Handle = nullptr;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
extern "C" __declspec(dllexport) int __cdecl UpdateANSMOTParameters(ANSCENTER::ANSMOT * *Handle, const char* trackerParameter) {
|
|
if (Handle == nullptr || *Handle == nullptr) return -1;
|
|
MOTHandleGuard guard(AcquireMOTHandle(*Handle));
|
|
if (!guard) return -1;
|
|
try {
|
|
bool result = guard.get()->UpdateParameters(trackerParameter);
|
|
if (result) return 1;
|
|
else return 0;
|
|
}
|
|
catch (std::exception& e) {
|
|
return 0;
|
|
}
|
|
catch (...) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
extern "C" __declspec(dllexport) int __cdecl UpdateANSMOT(ANSCENTER::ANSMOT * *Handle, int modelId, const char* detectionData, std::string & result) {
|
|
if (Handle == nullptr || *Handle == nullptr) return -1;
|
|
MOTHandleGuard guard(AcquireMOTHandle(*Handle));
|
|
if (!guard) return -1;
|
|
try {
|
|
result = guard.get()->Update(modelId, detectionData);
|
|
if (result.empty())return 0;
|
|
else return 1;
|
|
}
|
|
catch (std::exception& e) {
|
|
return 0;
|
|
}
|
|
catch (...) {
|
|
return 0;
|
|
}
|
|
}
|
|
extern "C" __declspec(dllexport) int __cdecl UpdateANSMOT_LV(ANSCENTER::ANSMOT * *Handle, int modelId, const char* detectionData, LStrHandle trackerResult) {
|
|
if (Handle == nullptr || *Handle == nullptr) return -1;
|
|
MOTHandleGuard guard(AcquireMOTHandle(*Handle));
|
|
if (!guard) return -1;
|
|
try {
|
|
std::string st = guard.get()->Update(modelId, detectionData);
|
|
int size = static_cast<int>(st.length());
|
|
MgErr error;
|
|
error = DSSetHandleSize(trackerResult, sizeof(int32) + size * sizeof(uChar));
|
|
if (error == noErr)
|
|
{
|
|
(*trackerResult)->cnt = size;
|
|
memcpy((*trackerResult)->str, st.c_str(), size);
|
|
return 1;
|
|
}
|
|
else return 0;
|
|
}
|
|
catch (std::exception& e) {
|
|
return 0;
|
|
}
|
|
catch (...) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
extern "C" __declspec(dllexport) int __cdecl UpdateANSMOTTracker(ANSCENTER::ANSMOT** Handle, int modelId, const std::vector<ANSCENTER::TrackerObject>& detectionObjects, std::vector<ANSCENTER::TrackerObject>& trackedObjects)
|
|
{
|
|
if (Handle == nullptr || *Handle == nullptr) return -1;
|
|
MOTHandleGuard guard(AcquireMOTHandle(*Handle));
|
|
if (!guard) return -1;
|
|
try {
|
|
trackedObjects = guard.get()->UpdateTracker(modelId, detectionObjects);
|
|
if (trackedObjects.empty()) return 0;
|
|
else return 1;
|
|
}
|
|
catch (std::exception& e) {
|
|
return 0;
|
|
}
|
|
catch (...) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// V2 LabVIEW API — Accept handle as uint64_t by value.
|
|
// Eliminates Handle** pointer-to-pointer instability when LabVIEW calls
|
|
// concurrently from multiple tasks.
|
|
// LabVIEW CLFN: set Handle parameter to Numeric / Unsigned Pointer-sized Integer / Pass: Value
|
|
// ============================================================================
|
|
|
|
extern "C" __declspec(dllexport) int __cdecl UpdateANSMOT_LV_V2(uint64_t handleVal, int modelId, const char* detectionData, LStrHandle trackerResult) {
|
|
ANSCENTER::ANSMOT* directHandle = reinterpret_cast<ANSCENTER::ANSMOT*>(handleVal);
|
|
if (directHandle == nullptr) return -1;
|
|
MOTHandleGuard guard(AcquireMOTHandle(directHandle));
|
|
if (!guard) return -1;
|
|
try {
|
|
std::string st = guard.get()->Update(modelId, detectionData);
|
|
int size = static_cast<int>(st.length());
|
|
MgErr error = DSSetHandleSize(trackerResult, sizeof(int32) + size * sizeof(uChar));
|
|
if (error == noErr) {
|
|
(*trackerResult)->cnt = size;
|
|
memcpy((*trackerResult)->str, st.c_str(), size);
|
|
return 1;
|
|
}
|
|
else return 0;
|
|
}
|
|
catch (...) { return 0; }
|
|
} |