Files
ANSCORE/modules/ANSTrainingEngine/ANSTrainingEngine.cpp

1225 lines
41 KiB
C++

#include "ANSTrainingEngine.h"
#include "ANSODTraininingEngine.h"
#include "ANSYOLOTrainingEngine.h"
#include "ANSYOLOCLTrainingEngine.h"
#include "ANSYOLOSEGTrainingEngine.h"
#include "ANSYOLOOBBTrainingEngine.h"
#include "Utility.h"
#include <random>
#include <cstdint>
#include <cstdio>
#include <memory>
#include <regex>
#include <string>
#include <vector>
#include <iostream>
#include <windows.h>
#include <tlhelp32.h>
#include <unordered_map>
#include <condition_variable>
// Handle registry with refcount — prevents use-after-free when
// ReleaseANSTREHandle is called while an operation is still running.
static std::unordered_map<ANSCENTER::ANSTRE*, int>& TREHandleRegistry() {
static std::unordered_map<ANSCENTER::ANSTRE*, int> s;
return s;
}
static std::mutex& TREHandleRegistryMutex() {
static std::mutex m;
return m;
}
static std::condition_variable& TREHandleRegistryCV() {
static std::condition_variable cv;
return cv;
}
static void RegisterTREHandle(ANSCENTER::ANSTRE* h) {
std::lock_guard<std::mutex> lk(TREHandleRegistryMutex());
TREHandleRegistry()[h] = 1;
}
static ANSCENTER::ANSTRE* AcquireTREHandle(ANSCENTER::ANSTRE* h) {
std::lock_guard<std::mutex> lk(TREHandleRegistryMutex());
auto it = TREHandleRegistry().find(h);
if (it == TREHandleRegistry().end()) return nullptr;
it->second++;
return h;
}
static bool ReleaseTREHandleRef(ANSCENTER::ANSTRE* h) {
std::lock_guard<std::mutex> lk(TREHandleRegistryMutex());
auto it = TREHandleRegistry().find(h);
if (it == TREHandleRegistry().end()) return false;
it->second--;
if (it->second <= 0) {
TREHandleRegistry().erase(it);
TREHandleRegistryCV().notify_all();
return true;
}
return false;
}
static bool UnregisterTREHandle(ANSCENTER::ANSTRE* h) {
std::unique_lock<std::mutex> lk(TREHandleRegistryMutex());
auto it = TREHandleRegistry().find(h);
if (it == TREHandleRegistry().end()) return false;
it->second--;
bool ok = TREHandleRegistryCV().wait_for(lk, std::chrono::seconds(30), [&]() {
auto it2 = TREHandleRegistry().find(h);
return it2 == TREHandleRegistry().end() || it2->second <= 0;
});
if (!ok) {
OutputDebugStringA("WARNING: UnregisterTREHandle timed out waiting for in-flight operations\n");
}
TREHandleRegistry().erase(h);
return true;
}
// RAII guard — ensures ReleaseTREHandleRef is always called
class TREHandleGuard {
ANSCENTER::ANSTRE* engine;
public:
explicit TREHandleGuard(ANSCENTER::ANSTRE* e) : engine(e) {}
~TREHandleGuard() { if (engine) ReleaseTREHandleRef(engine); }
ANSCENTER::ANSTRE* get() const { return engine; }
explicit operator bool() const { return engine != nullptr; }
TREHandleGuard(const TREHandleGuard&) = delete;
TREHandleGuard& operator=(const TREHandleGuard&) = delete;
};
template <typename T>
T getData(const boost::property_tree::ptree& pt, const std::string& key)
{
T ret;
if (boost::optional<T> data = pt.get_optional<T>(key))
{
ret = data.get();
}
return ret;
}
namespace ANSCENTER
{
bool ANSTRE::IsProcessRunning(const char* processName){
bool isRunning = false;
PROCESSENTRY32 processEntry;
processEntry.dwSize = sizeof(PROCESSENTRY32);
// Create a snapshot of all running processes
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE) {
// Handle error (e.g., log or return false)
return false;
}
if (Process32First(snapshot, &processEntry)) {
do {
#ifdef UNICODE
// Convert process name to wide string using proper UTF-8 conversion
int wideLen = MultiByteToWideChar(CP_UTF8, 0, processName, -1, nullptr, 0);
std::wstring wProcessName(wideLen > 0 ? wideLen - 1 : 0, L'\0');
if (wideLen > 0) MultiByteToWideChar(CP_UTF8, 0, processName, -1, &wProcessName[0], wideLen);
if (_wcsicmp(processEntry.szExeFile, wProcessName.c_str()) == 0) {
#else
// Compare the process name with the target process name (case-insensitive)
if (_stricmp(processEntry.szExeFile, processName) == 0) {
#endif
isRunning = true;
break;
}
} while (Process32Next(snapshot, &processEntry));
}
CloseHandle(snapshot);
return isRunning;
}
bool ANSTRE::ZipExperiment(std::string projectName, int experimentNumber) {
bool zipModelExist = false;
_projectName = Space2Underscore(projectName);
std::string projectPath = FindFilePathInFileList(_projects, _projectName);
if (FolderExist(projectPath)) {
std::string experimentPath = projectPath + "\\experiments\\" + std::to_string(experimentNumber);
std::string zipExperimentPath = experimentPath + ".zip";
std::string preTrainWeightFile = experimentPath + "\\train_last.pt";
if (FileExist(zipExperimentPath))fs::remove(zipExperimentPath);
if (ZipFolderWithPassword(experimentPath.c_str(), zipExperimentPath.c_str(), _zipPassword.c_str())) {
DeleteFolder(experimentPath);
}
return FileExist(zipExperimentPath);
}
else {
this->_logger.LogError("ANYLTRE::ANSTRE::ZipExperimen", "Invalid project path.", __FILE__, __LINE__);
return false;
}
}
double ANSTRE::ParseObjectDetectionMAP(std::string stEvaluationResult) {
std::regex valuePattern("all\\s+\\d+\\s+\\d+\\s+\\d\\.\\d+\\s+\\d\\.\\d+\\s+\\d\\.\\d+\\s+(\\d\\.\\d+)");
std::smatch matches;
if (std::regex_search(stEvaluationResult, matches, valuePattern) && matches.size() > 1) {
return std::atof(matches[1].str().c_str());
}
else {
return 0;
}
}
std::string ANSTRE::GetLatestValidFolderAndDeleteOthers(const std::string& projectName, const std::string& rootPath) {
if (!fs::exists(rootPath) || !fs::is_directory(rootPath)) {
std::cerr << "Error: Root path is invalid or not a directory." << std::endl;
return "";
}
std::vector<std::string> validFolderPath;
// Step 1: Scan all subdirectories matching projectName + number
for (const auto& entry : fs::directory_iterator(rootPath)) {
if (entry.is_directory()) {
//check if the folder has weights/best.pt
// convert entry.path() to string
std::string modelPath = entry.path().string() + "\\weights\\best.pt";
// check if this model path is exists
if (FileExist(modelPath))
{
validFolderPath.emplace_back(entry.path().string());
}
else {
//delete the folder
std::error_code ec;
fs::remove_all(entry.path(), ec);
}
}
}
// Step 2: the latest folder
fs::path selectedFolder;
if (!validFolderPath.empty()) {
selectedFolder = validFolderPath.back();
}
else {
return "";
}
// Step 3: Delete all other folders except for the selected one
if (validFolderPath.size() > 1) {
for (const auto& folder : validFolderPath) {
if (folder != selectedFolder && fs::exists(folder)) {
std::error_code ec;
fs::remove_all(folder, ec);
}
}
}
// Step 5: Rename the selected folder to the project name
std::string newFolderName = rootPath + "\\" + projectName;
//if selectedFolder is already the same as newFolderName, return
if (selectedFolder == newFolderName) {
return selectedFolder.string();
}
else {// rename the selected folder to the project name
std::error_code ec;
fs::rename(selectedFolder, newFolderName, ec);
// return new folder name
return newFolderName;
}
}
std::string ANSTRE::ExecuteCommand(const char* cmd) {
std::string result;
// Check if the command string is empty
if (cmd == nullptr || std::string(cmd).empty()) {
return ""; // Or simply return an empty string if no message is needed
}
STARTUPINFOA si;
PROCESS_INFORMATION pi;
SECURITY_ATTRIBUTES sa;
HANDLE hStdOutRead, hStdOutWrite;
// Set up the security attributes struct
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = nullptr;
// Create a pipe for the child process's STDOUT
if (!CreatePipe(&hStdOutRead, &hStdOutWrite, &sa, 0)) {
this->_logger.LogFatal("ANSTRE::ExecuteCommand()", "Failed to create pipe", __FILE__, __LINE__);
return "";
}
// Ensure the read handle to the pipe for STDOUT is not inherited
SetHandleInformation(hStdOutRead, HANDLE_FLAG_INHERIT, 0);
// Set up STARTUPINFO structure
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdOutput = hStdOutWrite;
si.hStdError = hStdOutWrite;
// Create the child process
std::string command = "cmd.exe /C " + std::string(cmd);
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcessA(nullptr, const_cast<char*>(command.c_str()), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &pi)) {
this->_logger.LogFatal("ANSTRE::ExecuteCommand()", "Failed to start process", __FILE__, __LINE__);
CloseHandle(hStdOutWrite);
CloseHandle(hStdOutRead);
return "";
}
// Close the write end of the pipe before reading from the read end
CloseHandle(hStdOutWrite);
// Read output from the child process
DWORD dwRead;
CHAR chBuf[4096];
ULONGLONG startTime = GetTickCount64();
ULONGLONG timeoutDuration = 180000; // 3 minutes
while (ReadFile(hStdOutRead, chBuf, 4096, &dwRead, nullptr) && dwRead != 0) {
result.append(chBuf, dwRead);
if ((GetTickCount64() - startTime) > timeoutDuration) break;
}
// Close the read handle of the pipe
CloseHandle(hStdOutRead);
// Close process and thread handles
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return result;
}
std::vector<std::string> ANSTRE::ParseANSClass(const std::string& ansClassFileName) {
std::vector<std::string> classNames;
// Create a property tree and parse the JSON file
boost::property_tree::ptree pt;
try {
boost::property_tree::read_json(ansClassFileName, pt);
// Iterate directly through the array
for (const auto& arrayElement : pt) {
classNames.push_back(arrayElement.second.get<std::string>("ClassName"));
}
}
catch (const boost::property_tree::ptree_bad_path& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
catch (const boost::property_tree::json_parser_error& e) {
std::cerr << "JSON Parsing Error: " << e.what() << std::endl;
}
return classNames;
}
std::string ANSTRE::ConvertVectorToClass(const std::vector<std::string>& vec) {
std::ostringstream oss;
oss << "[";
for (size_t i = 0; i < vec.size(); ++i)
{
oss << vec[i];
if (i < vec.size() - 1)
{
oss << ",";
}
}
oss << "]";
return oss.str();
}
}
extern "C" ANSTRE_API int CreateANSTREHandle(ANSCENTER::ANSTRE** Handle, const char* licenseKey, const char* projectDirectory, const char* engineDirectory, const char* modelTemplateDirectory, const char* modelZipPassword, int trainingEngineType, int latestEngine) {
if (Handle == nullptr) return 0;
if (licenseKey == nullptr || projectDirectory == nullptr || engineDirectory == nullptr || modelTemplateDirectory == nullptr || modelZipPassword == nullptr) return 0;
// Pure constructor: ignore *Handle(in). LabVIEW's CLF Node marshalling
// reuses the same temp buffer per call site, so *Handle(in) often holds
// leftover bytes from the previous Create's output even when the actual
// LabVIEW wire is a different, freshly-allocated instance. Inspecting
// *Handle(in) and destroying what we "see" tears down legitimate
// parallel instances. (Same reasoning as CreateANSAWSHandle.)
// Trade-off: a true double-Create on the same wire leaks the prior
// handle -- caller's bug; the alternative is far worse.
*Handle = nullptr;
try {
switch (trainingEngineType)
{
case 0:
(*Handle) = new ANSCENTER::ANSODTRE();
break;
case 1:
(*Handle) = new ANSCENTER::ANYLTRE();
break;
case 2:
(*Handle) = new ANSCENTER::ANYLCLTRE();
break;
case 3:
(*Handle) = new ANSCENTER::ANYLSEGTRE();
break;
case 4:
(*Handle) = new ANSCENTER::ANYLOBBTRE();
break;
default:
(*Handle) = new ANSCENTER::ANSODTRE();
break;
}
if (*Handle == nullptr) return 0;
bool isLatestEngine = (latestEngine == 1) ? true : false;
if ((*Handle)->Init(licenseKey, projectDirectory, engineDirectory, modelTemplateDirectory, modelZipPassword, isLatestEngine)) {
RegisterTREHandle(*Handle);
return 1;
}
delete *Handle; *Handle = nullptr;
return 0;
}
catch (std::exception& e) {
if (*Handle != nullptr) { delete *Handle; *Handle = nullptr; }
return 0;
}
catch (...) {
if (*Handle != nullptr) { delete *Handle; *Handle = nullptr; }
return 0;
}
}
static int ReleaseANSTREHandle_Impl(ANSCENTER::ANSTRE** Handle) {
try {
if (!Handle || !*Handle) return 1;
if (!UnregisterTREHandle(*Handle)) {
*Handle = nullptr;
return 1;
}
delete *Handle;
*Handle = nullptr;
return 1;
}
catch (...) {
if (Handle) *Handle = nullptr;
return 0;
}
}
extern "C" ANSTRE_API int ReleaseANSTREHandle(ANSCENTER::ANSTRE** Handle) {
__try {
return ReleaseANSTREHandle_Impl(Handle);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
if (Handle) *Handle = nullptr;
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GetProjects(ANSCENTER::ANSTRE** Handle, LStrHandle strProjects) {
if (Handle == nullptr || strProjects == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::vector<std::string> projects = guard.get()->GetProjects();
std::string st = VectorToSeparatedString(projects);
int size = (int)st.length();
MgErr error;
error = DSSetHandleSize(strProjects, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*strProjects)->cnt = size;
memcpy((*strProjects)->str, st.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GetProjectExperiments(ANSCENTER::ANSTRE** Handle, const char* projectName, LStrHandle strProjectExperiments) {
if (Handle == nullptr || projectName == nullptr || strProjectExperiments == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::vector<std::string> experiments = guard.get()->GetProjectExperiments(projectName);
std::string st = VectorToSeparatedString(experiments);
int size = (int)st.length();
MgErr error;
error = DSSetHandleSize(strProjectExperiments, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*strProjectExperiments)->cnt = size;
memcpy((*strProjectExperiments)->str, st.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_CreateProject(ANSCENTER::ANSTRE** Handle, const char* projectName) {
if (Handle == nullptr || projectName == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
if (guard.get()->CreateProject(stProjectName))return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_DeleteProject(ANSCENTER::ANSTRE** Handle, const char* projectName) {
if (Handle == nullptr || projectName == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
if (guard.get()->DeleteProject(stProjectName))return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_SetWorkingDirectory(ANSCENTER::ANSTRE** Handle, const char* workingDirectory) {
if (Handle == nullptr || workingDirectory == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stWorkingDirectory = workingDirectory;
if (guard.get()->SetWorkingDirectory(stWorkingDirectory))return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_UploadTrainingData(ANSCENTER::ANSTRE** Handle, const char* projectName) {
if (Handle == nullptr || projectName == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
if (guard.get()->UploadTrainingData(stProjectName))return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_CreateTrainingEngine(ANSCENTER::ANSTRE** Handle, const char* projectName, int experimentNumber, int extractorType, long numberStep, int batchSize, double learningRate) {
if (Handle == nullptr || projectName == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
if (guard.get()->CreateTrainingEngine(stProjectName, experimentNumber, extractorType, numberStep, batchSize, learningRate))return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GetProjectExperimentStatus(ANSCENTER::ANSTRE** Handle, const char* projectName, int experimentNumber, LStrHandle projectStatus) {
if (Handle == nullptr || projectName == nullptr || projectStatus == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
std::string stProjectStatus = guard.get()->GetProjectExperimentStatus(stProjectName, experimentNumber);
int size = (int)stProjectStatus.length();
MgErr error;
error = DSSetHandleSize(projectStatus, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*projectStatus)->cnt = size;
memcpy((*projectStatus)->str, stProjectStatus.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GenerateTrainingCommand(ANSCENTER::ANSTRE** Handle, const char* projectName, int experimentNumber, int extractorType, LStrHandle trainingCommand) {
if (Handle == nullptr || projectName == nullptr || trainingCommand == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
std::string stTrainingCommand = guard.get()->GenerateTrainingCommand(stProjectName, experimentNumber, extractorType);
int size = (int)stTrainingCommand.length();
MgErr error;
error = DSSetHandleSize(trainingCommand, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*trainingCommand)->cnt = size;
memcpy((*trainingCommand)->str, stTrainingCommand.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GenerateCustomTrainingCommand(ANSCENTER::ANSTRE** Handle, const char* projectName, int experimentNumber, int extractorType, const char* pretrainedModel, LStrHandle trainingCommand) {
if (Handle == nullptr || projectName == nullptr || pretrainedModel == nullptr || trainingCommand == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
std::string stTrainingCommand = guard.get()->GenerateCustomTrainingCommand(stProjectName, experimentNumber, extractorType, pretrainedModel);
int size = (int)stTrainingCommand.length();
MgErr error;
error = DSSetHandleSize(trainingCommand, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*trainingCommand)->cnt = size;
memcpy((*trainingCommand)->str, stTrainingCommand.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_EvaluateModel(ANSCENTER::ANSTRE** Handle, const char* projectName, int experimentNumber, LStrHandle mAPResult) {
if (Handle == nullptr || projectName == nullptr || mAPResult == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
std::string stmAPResult = guard.get()->EvaluateModel(stProjectName, experimentNumber);
int size = (int)stmAPResult.length();
MgErr error;
error = DSSetHandleSize(mAPResult, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*mAPResult)->cnt = size;
memcpy((*mAPResult)->str, stmAPResult.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_DownloadModel(ANSCENTER::ANSTRE** Handle, const char* projectName, int experimentNumber, const char* downloadDirDestination, int modelMode)
{
if (Handle == nullptr || projectName == nullptr || downloadDirDestination == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
bool downloadResult = guard.get()->DownloadModel(stProjectName, experimentNumber, downloadDirDestination, modelMode);
if (downloadResult)return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GetProjectDirectory(ANSCENTER::ANSTRE** Handle, LStrHandle strProjectDir) {
if (Handle == nullptr || strProjectDir == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectDir = guard.get()->GetProjectDirectory();
int size = (int)stProjectDir.length();
MgErr error;
error = DSSetHandleSize(strProjectDir, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*strProjectDir)->cnt = size;
memcpy((*strProjectDir)->str, stProjectDir.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_ZipExperiment(ANSCENTER::ANSTRE** Handle, const char* projectName, int experimentNumber) {
if (Handle == nullptr || projectName == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
if (guard.get()->ZipExperiment(stProjectName, experimentNumber))return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API double ANSTRE_ParseMAP(ANSCENTER::ANSTRE** Handle, const char* evaluationResult) {
if (Handle == nullptr || evaluationResult == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stEvaluationResult = evaluationResult;
return guard.get()->ParseObjectDetectionMAP(stEvaluationResult);
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_ParseTrainingResults(ANSCENTER::ANSTRE** Handle, const char* trainingResult, LStrHandle strResult) {
if (Handle == nullptr || trainingResult == nullptr || strResult == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stTrainingResult = trainingResult;
std::string stResult = guard.get()->ParseTrainingResults(stTrainingResult);
int size = (int)stResult.length();
MgErr error;
error = DSSetHandleSize(strResult, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*strResult)->cnt = size;
memcpy((*strResult)->str, stResult.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
//CPP interface
extern "C" ANSTRE_API int ANSTRE_GetProjects_CPP(ANSCENTER::ANSTRE** Handle, std::string& strProjects) {
if (Handle == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::vector<std::string> projects = guard.get()->GetProjects();
strProjects = VectorToSeparatedString(projects);
return 1;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GetProjectExperiments_CPP(ANSCENTER::ANSTRE** Handle, const char* projectName, std::string& strProjectExperiments) {
if (Handle == nullptr || projectName == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::vector<std::string> experiments = guard.get()->GetProjectExperiments(projectName);
strProjectExperiments = VectorToSeparatedString(experiments);
return 1;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GetProjectExperimentStatus_CPP(ANSCENTER::ANSTRE** Handle, const char* projectName, int experimentNumber, std::string& projectStatus) {
if (Handle == nullptr || projectName == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
projectStatus = guard.get()->GetProjectExperimentStatus(stProjectName, experimentNumber);
return 1;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GenerateTrainingCommand_CPP(ANSCENTER::ANSTRE** Handle, const char* projectName, int experimentNumber, int extractorType, std::string& trainingCommand) {
if (Handle == nullptr || projectName == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
trainingCommand = guard.get()->GenerateTrainingCommand(stProjectName, experimentNumber, extractorType);
return 1;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GenerateCustomTrainingCommand_CPP(ANSCENTER::ANSTRE** Handle, const char* projectName, int experimentNumber, int extractorType, const char* pretrainedModel, std::string& trainingCommand) {
if (Handle == nullptr || projectName == nullptr || pretrainedModel == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
trainingCommand = guard.get()->GenerateCustomTrainingCommand(stProjectName, experimentNumber, extractorType, pretrainedModel);
return 1;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_EvaluateModel_CPP(ANSCENTER::ANSTRE** Handle, const char* projectName, int experimentNumber, std::string& mAPResult) {
if (Handle == nullptr || projectName == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
mAPResult = guard.get()->EvaluateModel(stProjectName, experimentNumber);
return 1;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_EvaluateModelOnTestData_CPP(ANSCENTER::ANSTRE** Handle, const char* projectName, int experimentNumber, const char* dataFolder,std::string& evaluationCommand) {
if (Handle == nullptr || projectName == nullptr || dataFolder == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
bool zipModelExist = false;
evaluationCommand = guard.get()->GenerateTestCommand(stProjectName, experimentNumber, zipModelExist, dataFolder);
if (evaluationCommand.empty()) {
return 0;
}
else {
return 1;
}
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_EvaluateModelOnTestData(ANSCENTER::ANSTRE** Handle, const char* projectName, int experimentNumber, const char* dataFolder, LStrHandle evaluationCommand) {
if (Handle == nullptr || projectName == nullptr || dataFolder == nullptr || evaluationCommand == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
bool zipModelExist = false;
std::string evaluationCommandStr = guard.get()->GenerateTestCommand(stProjectName, experimentNumber, zipModelExist, dataFolder);
int size = (int)evaluationCommandStr.length();
MgErr error;
error = DSSetHandleSize(evaluationCommand, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*evaluationCommand)->cnt = size;
memcpy((*evaluationCommand)->str, evaluationCommandStr.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GetProjectDirectory_CPP(ANSCENTER::ANSTRE** Handle, std::string& strProjectDir) {
if (Handle == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
strProjectDir = guard.get()->GetProjectDirectory();
return 1;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_ParseTrainingResults_CPP(ANSCENTER::ANSTRE** Handle, const char* trainingResult, std::string& strResult) {
if (Handle == nullptr || trainingResult == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
std::string stTrainingResult = trainingResult;
strResult = guard.get()->ParseTrainingResults(stTrainingResult);
return 1;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_CheckEngineStatus(ANSCENTER::ANSTRE** Handle) {
if (Handle == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
bool bResult = guard.get()->CheckEngineStatus();
if (bResult) return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_CheckEngine(ANSCENTER::ANSTRE** Handle) {
if (Handle == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(*Handle));
if (!guard) return 0;
try {
bool bResult = guard.get()->CheckEngine();
if (bResult) return 1;
else return 0;
}
catch (...) {
return 0;
}
}
// ============================================================================
// V2 API — accepts uint64_t handleVal by value instead of ANSTRE** Handle.
// Eliminates LabVIEW buffer-reuse bug when concurrent calls share the same
// Handle** buffer address.
// ============================================================================
extern "C" ANSTRE_API int ANSTRE_GetProjects_V2(uint64_t handleVal, LStrHandle strProjects) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (strProjects == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::vector<std::string> projects = guard.get()->GetProjects();
std::string st = VectorToSeparatedString(projects);
int size = (int)st.length();
MgErr error;
error = DSSetHandleSize(strProjects, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*strProjects)->cnt = size;
memcpy((*strProjects)->str, st.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GetProjectExperiments_V2(uint64_t handleVal, const char* projectName, LStrHandle strProjectExperiments) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (projectName == nullptr || strProjectExperiments == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::vector<std::string> experiments = guard.get()->GetProjectExperiments(projectName);
std::string st = VectorToSeparatedString(experiments);
int size = (int)st.length();
MgErr error;
error = DSSetHandleSize(strProjectExperiments, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*strProjectExperiments)->cnt = size;
memcpy((*strProjectExperiments)->str, st.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_CreateProject_V2(uint64_t handleVal, const char* projectName) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (projectName == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
if (guard.get()->CreateProject(stProjectName))return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_DeleteProject_V2(uint64_t handleVal, const char* projectName) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (projectName == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
if (guard.get()->DeleteProject(stProjectName))return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_SetWorkingDirectory_V2(uint64_t handleVal, const char* workingDirectory) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (workingDirectory == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::string stWorkingDirectory = workingDirectory;
if (guard.get()->SetWorkingDirectory(stWorkingDirectory))return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_UploadTrainingData_V2(uint64_t handleVal, const char* projectName) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (projectName == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
if (guard.get()->UploadTrainingData(stProjectName))return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_CreateTrainingEngine_V2(uint64_t handleVal, const char* projectName, int experimentNumber, int extractorType, long numberStep, int batchSize, double learningRate) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (projectName == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
if (guard.get()->CreateTrainingEngine(stProjectName, experimentNumber, extractorType, numberStep, batchSize, learningRate))return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GetProjectExperimentStatus_V2(uint64_t handleVal, const char* projectName, int experimentNumber, LStrHandle projectStatus) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (projectName == nullptr || projectStatus == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
std::string stProjectStatus = guard.get()->GetProjectExperimentStatus(stProjectName, experimentNumber);
int size = (int)stProjectStatus.length();
MgErr error;
error = DSSetHandleSize(projectStatus, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*projectStatus)->cnt = size;
memcpy((*projectStatus)->str, stProjectStatus.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GenerateTrainingCommand_V2(uint64_t handleVal, const char* projectName, int experimentNumber, int extractorType, LStrHandle trainingCommand) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (projectName == nullptr || trainingCommand == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
std::string stTrainingCommand = guard.get()->GenerateTrainingCommand(stProjectName, experimentNumber, extractorType);
int size = (int)stTrainingCommand.length();
MgErr error;
error = DSSetHandleSize(trainingCommand, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*trainingCommand)->cnt = size;
memcpy((*trainingCommand)->str, stTrainingCommand.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GenerateCustomTrainingCommand_V2(uint64_t handleVal, const char* projectName, int experimentNumber, int extractorType, const char* pretrainedModel, LStrHandle trainingCommand) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (projectName == nullptr || pretrainedModel == nullptr || trainingCommand == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
std::string stTrainingCommand = guard.get()->GenerateCustomTrainingCommand(stProjectName, experimentNumber, extractorType, pretrainedModel);
int size = (int)stTrainingCommand.length();
MgErr error;
error = DSSetHandleSize(trainingCommand, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*trainingCommand)->cnt = size;
memcpy((*trainingCommand)->str, stTrainingCommand.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_EvaluateModel_V2(uint64_t handleVal, const char* projectName, int experimentNumber, LStrHandle mAPResult) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (projectName == nullptr || mAPResult == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
std::string stmAPResult = guard.get()->EvaluateModel(stProjectName, experimentNumber);
int size = (int)stmAPResult.length();
MgErr error;
error = DSSetHandleSize(mAPResult, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*mAPResult)->cnt = size;
memcpy((*mAPResult)->str, stmAPResult.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_EvaluateModelOnTestData_V2(uint64_t handleVal, const char* projectName, int experimentNumber, const char* dataFolder, LStrHandle evaluationCommand) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (projectName == nullptr || dataFolder == nullptr || evaluationCommand == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
bool zipModelExist = false;
std::string evaluationCommandStr = guard.get()->GenerateTestCommand(stProjectName, experimentNumber, zipModelExist, dataFolder);
int size = (int)evaluationCommandStr.length();
MgErr error;
error = DSSetHandleSize(evaluationCommand, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*evaluationCommand)->cnt = size;
memcpy((*evaluationCommand)->str, evaluationCommandStr.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_DownloadModel_V2(uint64_t handleVal, const char* projectName, int experimentNumber, const char* downloadDirDestination, int modelMode) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (projectName == nullptr || downloadDirDestination == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
bool downloadResult = guard.get()->DownloadModel(stProjectName, experimentNumber, downloadDirDestination, modelMode);
if (downloadResult)return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_GetProjectDirectory_V2(uint64_t handleVal, LStrHandle strProjectDir) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (strProjectDir == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::string stProjectDir = guard.get()->GetProjectDirectory();
int size = (int)stProjectDir.length();
MgErr error;
error = DSSetHandleSize(strProjectDir, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*strProjectDir)->cnt = size;
memcpy((*strProjectDir)->str, stProjectDir.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_ZipExperiment_V2(uint64_t handleVal, const char* projectName, int experimentNumber) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (projectName == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::string stProjectName = projectName;
if (guard.get()->ZipExperiment(stProjectName, experimentNumber))return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API double ANSTRE_ParseMAP_V2(uint64_t handleVal, const char* evaluationResult) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0.0;
if (evaluationResult == nullptr) return 0.0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0.0;
try {
std::string stEvaluationResult = evaluationResult;
return guard.get()->ParseObjectDetectionMAP(stEvaluationResult);
}
catch (...) {
return 0.0;
}
}
extern "C" ANSTRE_API int ANSTRE_ParseTrainingResults_V2(uint64_t handleVal, const char* trainingResult, LStrHandle strResult) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
if (trainingResult == nullptr || strResult == nullptr) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
std::string stTrainingResult = trainingResult;
std::string stResult = guard.get()->ParseTrainingResults(stTrainingResult);
int size = (int)stResult.length();
MgErr error;
error = DSSetHandleSize(strResult, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*strResult)->cnt = size;
memcpy((*strResult)->str, stResult.c_str(), size);
return 1;
}
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_CheckEngineStatus_V2(uint64_t handleVal) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
bool bResult = guard.get()->CheckEngineStatus();
if (bResult) return 1;
else return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSTRE_API int ANSTRE_CheckEngine_V2(uint64_t handleVal) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSTRE*>(handleVal);
if (!_v2h) return 0;
TREHandleGuard guard(AcquireTREHandle(_v2h));
if (!guard) return 0;
try {
bool bResult = guard.get()->CheckEngine();
if (bResult) return 1;
else return 0;
}
catch (...) {
return 0;
}
}