archimedes.codegen

archimedes.codegen(
func: Callable | FunctionCache,
args: Sequence[Any],
static_argnums: int | Sequence[int] | None = None,
static_argnames: str | Sequence[str] | None = None,
return_names: Sequence[str] | None = None,
kwargs: dict[str, Any] | None = None,
float_type: type = float,
int_type: type = int,
input_descriptions: dict[str, str] | None = None,
output_descriptions: dict[str, str] | None = None,
output_dir: str | None = None,
options: dict[str, Any] | None = None,
debug: bool = False,
) None

Generate C/C++ code from a compiled function.

Creates standalone C or C++ code that implements the computational graph defined by the function. This allows Archimedes models to be deployed on embedded systems, integrated into C/C++ codebases, or compiled to native executables for maximum performance.

For a detailed description of the codegen functionality, see the guide to code generation and hardware deployment.

Parameters:
  • func (Callable | FunctionCache) – The compiled function to generate code for. If not already a FunctionCache, it will be compiled automatically.

  • args (tuple) –

    Arguments to the function that specify shapes and dtypes. These can be:

    • SymbolicArray objects

    • NumPy arrays with the same shape and dtype as expected inputs

    • [tree-structured data types](../../trees.md) matching expected inputs

    • The actual values for static arguments

    Note: For dynamic arguments, the numeric values are ignored.

  • static_argnums (tuple, optional) – The indices of the static arguments to the function. Will be ignored if func is already a FunctionCache.

  • static_argnames (tuple, optional) – The names of the static arguments to the function. Will be ignored if func is already a FunctionCache.

  • return_names (tuple, optional) – The names of the return values of the function. Ignored if func is already a FunctionCache. For the sake of readability, this argument is required to be provided, either directly or when separately compiling the function to a FunctionCache.

  • kwargs (dict, optional) – Keyword arguments to pass to the function during specialization.

  • float_type (type, default=float) – The C type to use for floating point numbers.

  • int_type (type, default=int) – The C type to use for integers.

  • input_descriptions (dict[str, str], optional) – Descriptions for the input arguments. Used for generating comments in the code.

  • output_descriptions (dict[str, str], optional) – Descriptions for the output values. Used for generating comments in the code.

  • output_dir (str, optional) – Path where the generated code will be written.

  • options (dict, optional) –

    Additional options for code generation. This can include:

    • verbose: If True, include additional comments in the generated code.

    • with_mem: If True, generate a simplified C API with memory helpers.

    • indent: The number of spaces to use for indentation in the generated code.

  • debug (bool, default=False) – If True, print debugging information about the codegen process. Useful for development purposes only and subject to removal in future versions.

Returns:

The function writes the generated code to the specified file(s).

Return type:

None

Notes

Use this for:

  • Deploying models on embedded systems or hardware without Python

  • Integrating Archimedes algorithms into C/C++ applications

  • Maximum runtime performance by removing Python interpreter overhead

  • Creating standalone, portable implementations of your algorithm

This function specializes the computational graph of func to specific input shapes and types, then uses CasADi’s code generation capabilities to produce C code that implements the same computation. The generated code has no dependencies on Archimedes, CasADi, or Python.

Currently, this function uses CasADi’s code generation directly, so the generated code will contain CASADI_* prefixes and follow CasADi’s conventions. The function will also generate an “interface” API layer with struct definitions for inputs and outputs, along with convenience functions for initialization and function calls.

Generated API

The codegen guide has a detailed description of how to use the generated API. In short, a Python function named func will generate three top-level C structs:

  1. func_arg_t: Arguments to func

  2. func_res_t: Return values of func

  3. func_work_t: Pre-allocated temporary workspace variables

There will also be two generated functions:

  1. func_init: Initializes the argument and workspace structs

  2. func_step: Calls the main computation function

The basic pattern for using this API is:

// Allocate all structs on the stack
func_arg_t arg;
func_res_t res;
func_work_t work;

func_init(&arg, &res, &work);  // Initialize using the template values
func_step(&arg, &res, &work);  // Numerically evaluate the function

If the function is “stateful”, meaning some outputs are recursively looped back to the inputs, manual copying of the state will be required. See below for details.

Numerical constants

To store numerical constants in the generated code, either:

  1. “Close over” the values in your function definition

  2. Pass them as hashable static arguments (same effect as a closure)

  3. Pass as “dynamic” arguments that could be edited in the generated code

Support for structured data types

The code generation system supports structured data types, either as homogeneous arrays (lists or tuples with all elements of the same type) or as heterogeneous containers (e.g. dictionaries, named tuples, or struct() classes. The former will be represented as C arrays, while the latter will be represented as C structs.

For example, a struct argument defined with

@struct
class Point:
    x: float
    y: float

will autogenerate a C struct:

typedef struct {
    float x;
    float y;
} point_t;

Stateful functions

A common pattern for dynamics models or control algorithms is to have functions that implement a generic discrete-time state-space model of the form

\[ \begin{align}\begin{aligned}x_{k+1} = f(x_k, u_k)\\y_k = g(x_k, u_k)\end{aligned}\end{align} \]

This can be combined into a single function with the signature func(x[k], u[k]) -> (x[k+1], y[k]). When working with functions of this form (or any similar stateful functions), the generated code will still be “functionally pure”, meaning that the result data will store x[k+1] and the argument data will store x[k], but the updated state will not automatically be copied back to the input.

If the state is implemented as a @struct, it will correspond to a C struct and the copy operation can be implemented simply using direct copy semantics. For example, a function with the signature func(state, inputs) -> (state_new, outputs) for which the state is a @struct (or dict, or named tuple) will generate a C struct named state_t. The arg structure will include a field state, and the res structure will include a field state_new, both of which have type state_t. With direct assignment copying, the updated state can be copied back to the input with

arg.state = res.state_new;

Examples

>>> import numpy as np
>>> import archimedes as arc
>>>
>>> # Define a simple function
>>> @arc.compile
... def rotate(x, theta):
...     R = np.array([
...         [np.cos(theta), -np.sin(theta)],
...         [np.sin(theta), np.cos(theta)],
...     ], like=x)
...     return R @ x
>>>
>>> # Create templates with appropriate shapes and dtypes
>>> x_type = np.zeros((2,), dtype=float)
>>> theta_type = np.array(0.0, dtype=float)
>>>
>>> # Generate C code
>>> arc.codegen(rotate, (x_type, theta_type))

The above code will generate files including ‘rotate.c’ and ‘rotate.h’ that implement the rotation function in C.

To use numerical constants, declaring arguments as static will fix the value in the generated code:

>>> @arc.compile(static_argnames=("scale",))
... def scaled_rotation(x, theta, scale=2.0):
...     R = np.array([
...         [np.cos(theta), -np.sin(theta)],
...         [np.sin(theta), np.cos(theta)],
...     ], like=x)
...     return scale * (R @ x)
>>>
>>> arc.codegen(scaled_rotation, (x_type, theta_type, 5.0))

See also

compile

Create a compiled function for use with codegen