Adds what the folder was missing for someone picking it up cold.
as-built/ the STruC++ output copied out of the live container - the C++
the PLC is actually executing, plus program.st and the Modbus
buffer config. The running image was made with docker commit
and exists in no registry, so this is the only other copy of
the compiled form.
Verified while copying: the deployed program.st matches
build/wrps.st generated from src/. Identical POU structure,
ZERO differences in non-declaration lines. src/ is genuinely
canonical and the running PLC agrees with it.
VERSIONS.md every version read from the running system, not from
documentation: runtime v4.1.10, STruC++ 0.6.2, Editor
4.2.11, Debian 12, g++ 12.2, pymodbus 3.11.2, CI
Server R1.03. Plus which plugins are enabled -
ethercat is on for no reason - and a v3-vs-v4 table,
since most OpenPLC guidance online is for v3 and the
%MW HR1024 change silently produces wrong data.
GETTING-STARTED.md three questions answered in a page: how to modify the
program, how to stand up a new PLC container from
scratch, how to move this one. Includes the compose
file, the Editor steps that are not generated and are
always missed, and a symptom-to-document table.
94 lines
2.4 KiB
C++
94 lines
2.4 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later WITH STruCpp-runtime-exception
|
|
// Copyright (C) 2025 Autonomy / OpenPLC Project
|
|
// This file is part of the STruC++ Runtime Library and is covered by the
|
|
// STruC++ Runtime Library Exception. See COPYING.RUNTIME for details.
|
|
/**
|
|
* STruC++ Runtime - IEC Dynamic Memory Allocation
|
|
*
|
|
* Implements CODESYS-compatible __NEW/__DELETE operators for dynamic memory.
|
|
* Uses malloc/free with placement new for allocation to match IEC semantics:
|
|
* - Returns nullptr (0) on failure (no exceptions)
|
|
* - __DELETE sets pointer to nullptr after freeing
|
|
* - Array allocation constructs each element
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <cstdlib>
|
|
#include <cstddef>
|
|
#include <new>
|
|
#include "iec_ptr.hpp"
|
|
|
|
namespace strucpp {
|
|
|
|
/**
|
|
* Allocate and construct a single object of type T.
|
|
* Returns nullptr on allocation failure.
|
|
*/
|
|
template<typename T>
|
|
T* iec_new() {
|
|
void* mem = std::malloc(sizeof(T));
|
|
if (!mem) return nullptr;
|
|
return new (mem) T(); // Placement new for construction
|
|
}
|
|
|
|
/**
|
|
* Allocate and construct an array of count elements of type T.
|
|
* Returns nullptr on allocation failure.
|
|
*/
|
|
template<typename T>
|
|
T* iec_new_array(std::size_t count) {
|
|
if (count == 0) return nullptr;
|
|
void* mem = std::malloc(sizeof(T) * count);
|
|
if (!mem) return nullptr;
|
|
T* arr = static_cast<T*>(mem);
|
|
for (std::size_t i = 0; i < count; ++i) {
|
|
new (&arr[i]) T(); // Construct each element
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
/**
|
|
* Deallocate a single object. Sets pointer to nullptr after freeing.
|
|
* Safe to call with nullptr (no-op).
|
|
*/
|
|
template<typename T>
|
|
void iec_delete(T*& ptr) {
|
|
if (ptr) {
|
|
ptr->~T(); // Call destructor
|
|
std::free(ptr);
|
|
ptr = nullptr;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deallocate via IEC_Ptr. Extracts raw pointer, frees, and resets to nullptr.
|
|
*/
|
|
template<typename T>
|
|
void iec_delete(IEC_Ptr<T>& ptr) {
|
|
T* raw = ptr.get();
|
|
if (raw) {
|
|
raw->~T();
|
|
std::free(raw);
|
|
ptr = nullptr;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deallocate an array of objects. Sets pointer to nullptr after freeing.
|
|
* Note: For simplicity, this uses the same iec_delete since we don't
|
|
* track array sizes. The destructor for individual elements is trivial
|
|
* for IEC elementary types.
|
|
*/
|
|
template<typename T>
|
|
void iec_delete_array(T*& ptr, std::size_t count) {
|
|
if (ptr) {
|
|
for (std::size_t i = 0; i < count; ++i) {
|
|
ptr[i].~T();
|
|
}
|
|
std::free(ptr);
|
|
ptr = nullptr;
|
|
}
|
|
}
|
|
|
|
} // namespace strucpp
|