FFI API
FFI API
This page explains the PHP/C binding layer and memory safety rules for the tensor engine.
Pml\Lib\TensorEngine
TensorEngine exposes libtensor.so via PHP FFI::cdef().
get()
public static function get(): \FFI
- Lazily builds
libtensor.soif it does not exist. - Returns a cached
FFIinstance. - Declares all native functions used by the framework.
Native C functions exposed
The following groups are available through TensorEngine:
- Tensor creation and destruction
- Arithmetic and comparison kernels
- Linear algebra, BLAS, and matrix operations
- Convolution, im2col, and attention operations
- CSV dataset ingestion
- SafeTensors file save/load
- Threading configuration
- KV cache and inference primitives
Error handling
All native calls should be followed by tensor_check_error().
TensorEngine::get() exposes:
bool tensor_check_error(void);
const char* tensor_get_last_error(void);
void tensor_clear_error(void);
The PHP wrappers translate C errors into RuntimeException.
Memory safety
Ownership semantics
Tensorobjects own theirTensorC*pointer by default.Tensor::wrap()can accept aparenttensor to preserve shared ownership.- When a
Tensoris a view, theparentreference prevents the original storage from being freed. - Native arena allocations are supported; arena-backed tensors are not freed individually.
SafeTensors and mmap
Pml\Lib\SafeTensorsIOwrites tensor bytes with zero PHP heap copies.Tensor::fromMmap()maps a file region into memory and returns a tensor backed by the OS page cache.mmapFree()must be called to release the mapping when the tensor is no longer needed.
CSV ingestion
tensor_dataset_from_csv()is the fastest path for numeric-only CSV files.- Mixed-type CSVs fall back to ETL mode via
df_read_csv(). - The C dataset loader uses memory-efficient parsing and avoids loading entire files into PHP arrays.
Threading
Control CPU parallelism using:
Tensor::configureThreading(int $ompThreads, int $blasThreads = 1): void
ompThreadscontrols OpenMP kernels.blasThreadscontrols the underlying BLAS thread pool.
Example Usage
use Pml\Tensor;
Tensor::configureThreading(4, 1);
$t = Tensor::randomNormal([1024, 1024]);
$u = $t->transpose()->matmul($t);
Common mistakes
- Calling native C functions without checking
tensor_check_error(). - Releasing mmap-backed tensors by relying solely on PHP GC instead of
mmapFree(). - Assuming
Tensor::wrap()always transfers ownership; shared parent references may keep memory alive.