C-Block Python API Reference¶
All public symbols are importable from pulsim.cblock and re-exported from
pulsim directly.
from pulsim.cblock import compile_cblock, CBlockLibrary, PythonCBlock
# or:
from pulsim import compile_cblock, CBlockLibrary, PythonCBlock
detect_compiler¶
def detect_compiler() -> str | None
Find a suitable C compiler on the current machine.
Discovery order:
PULSIM_CCenvironment variable (overrides everything).- POSIX: tries
cc,gcc,clangin order (viashutil.which). - Windows: tries
cl.exe, thengcc.
Returns the full path to the executable, or None if nothing is found.
compile_cblock¶
def compile_cblock(
source: str | Path,
*,
output_dir: str | Path | None = None,
name: str = "cblock",
extra_cflags: list[str] | None = None,
compiler: str | None = None,
) -> Path
Compile a .c source file (or inline C source string) into a shared library.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
source |
str | Path |
— | Path to a .c file, or a string containing C source code |
output_dir |
str | Path | None |
None |
Directory for the output library; defaults to a temporary directory (tempfile.mkdtemp()) |
name |
str |
"cblock" |
Stem of the output filename (name.so / name.dylib / name.dll) |
extra_cflags |
list[str] | None |
None |
Extra compiler flags appended after the defaults (e.g. ["-lm", "-I/usr/include/mylib"]) |
compiler |
str | None |
None |
Explicit compiler path; when None, falls back to PULSIM_CC env var, then detect_compiler() |
Compiler priority: explicit compiler argument → PULSIM_CC env var →
auto-detect (detect_compiler()).
Default flags added automatically:
- POSIX:
-O2 -shared -fPIC -std=c11 -Wall -Wextra - MSVC:
/LD /O2
Returns: Path to the compiled shared library.
Raises:
CBlockCompileError— compiler executable not found, or process exits non-zero. Attributes:.compiler_path(str | None),.source(str),.stderr_output(str).
CBlockLibrary¶
class CBlockLibrary:
def __init__(
self,
lib_path: str | Path,
n_inputs: int = 1,
n_outputs: int = 1,
name: str = "",
) -> None
Loads a compiled shared library and wraps it in the CBlock interface.
Constructor behaviour:
- Loads the library via
ctypes.CDLL. - Reads
pulsim_cblock_abi_versionand raisesCBlockABIErrorif the value differs fromPULSIM_CBLOCK_ABI_VERSION. - Resolves
pulsim_cblock_step(required) and raisesCBlockABIErrorif the symbol is absent. - Resolves
pulsim_cblock_initandpulsim_cblock_destroy(optional). - Calls
pulsim_cblock_initif present.
Properties¶
| Property | Type | Description |
|---|---|---|
n_inputs |
int |
Number of scalar input channels |
n_outputs |
int |
Number of scalar output channels |
name |
str |
Block name (from constructor or from library metadata) |
step¶
def step(self, t: float, dt: float, inputs: Sequence[float]) -> list[float]
Call pulsim_cblock_step with one simulation timestep.
t— current simulation time [s]dt— elapsed time since previous accepted step [s]; pass0.0at first stepinputs— sequence ofn_inputsfloats (list, tuple, or numpy array)
Returns a list[float] of length n_outputs.
Raises CBlockRuntimeError if the C function returns a nonzero value.
reset¶
def reset(self) -> None
Re-initialise the block state: calls pulsim_cblock_destroy (if present) then
pulsim_cblock_init (if present). Any internal state accumulated during
simulation is discarded.
Context manager¶
with CBlockLibrary(lib_path, n_inputs=1, n_outputs=1) as blk:
blk.step(0.0, 1e-6, [1.0])
# destroy called, library unloaded
__enter__ returns self; __exit__ calls pulsim_cblock_destroy and
unloads the library.
PythonCBlock¶
class PythonCBlock:
def __init__(
self,
fn: Callable[[dict, float, float, list[float]], list[float]],
n_inputs: int,
n_outputs: int,
name: str = "",
) -> None
Wraps a Python callable so it can be used wherever a CBlockLibrary is
expected — no C compiler required.
fn signature:
def fn(ctx: dict, t: float, dt: float, inputs: list[float]) -> list[float]:
...
ctxis a plaindictshared across calls — store any state you need there.- Must return a list of exactly
n_outputsfloats.
Properties¶
Same as CBlockLibrary: n_inputs, n_outputs, name.
step¶
def step(self, t: float, dt: float, inputs: Sequence[float]) -> list[float]
Calls fn(self._ctx, t, dt, list(inputs)) and returns its result.
reset¶
def reset(self) -> None
Clears the internal ctx dict (self._ctx = {}).
Exceptions¶
CBlockCompileError¶
Raised by compile_cblock() when the compilation fails.
| Attribute | Type | Description |
|---|---|---|
compiler_path |
str | None |
Path to the compiler that was used (or attempted) |
source |
str |
Source text or source path that was compiled |
stderr_output |
str |
Full stderr from the compiler process |
CBlockABIError¶
Raised by CBlockLibrary.__init__() when the library's ABI version does not
match, or when a required symbol is missing.
| Attribute | Type | Description |
|---|---|---|
expected_version |
int |
PULSIM_CBLOCK_ABI_VERSION at load time |
found_version |
int | None |
Version read from the library; None if the version symbol was absent |
CBlockRuntimeError¶
Raised by CBlockLibrary.step() when pulsim_cblock_step returns a nonzero value.
| Attribute | Type | Description |
|---|---|---|
return_code |
int |
Value returned by C step |
t |
float |
Simulation time at which the error occurred [s] |
step_index |
int |
Step counter (0-based) |
pulsim.capabilities¶
import pulsim
assert pulsim.capabilities["c_block"] is True
Module-level dict that advertises optional feature availability.
Downstream code and GUI tools can check pulsim.capabilities["c_block"] before
offering C-Block functionality to end users.