ANSI C auf evrtng functions

Führen Sie nativen C-Code als Serverless-Funktion mit einer benutzerdefinierten Docker-Runtime auf evrtng functions aus. Maximale Performance, null Server zu verwalten.

ANSI C / GCC Docker Runtime Binary Runtime

Warum ANSI C?

Die Binary-Runtime führt Ihr kompiliertes C-Programm direkt aus — sein stdout wird zum HTTP-Response-Body. Das Binary in ein kleines Image packen, fertig ist die serverless C-Funktion. Das bringt Ihnen:

Nahezu native Performance Kompiliertes C wird direkt ausgeführt — kein Interpreter-Overhead.
Winziges Container-Image Ein statisch gelinktes C-Binary kann ein Container-Image unter 10 MB erzeugen.
Vollständige C-Standardbibliothek GCC, libc und jede Bibliothek, die Sie brauchen — volle Kontrolle via Dockerfile.
Tenant-URL inklusive Ihre Funktion bekommt ihren eigenen HTTPS-Endpunkt — Aufruf mit curl, kein Gateway-Setup.

// Voraussetzungen

API Key evrtng-functions-API-Key (Header X-API-Key) Docs →
Docker Docker Desktop oder Docker Engine lokal ausgeführt Docs →
GCC GCC-Compiler für lokale Tests (optional)
Registry Docker Hub oder eine öffentlich pullbare Registry Docs →
Auth Key evrtng functions API-Key aus Ihrem Konto Docs →
check prerequisites
# API reachable (401 = yes, alive and requiring your key)
$ curl -s -o /dev/null -w "%{http_code}" https://fnc4.evrtng.cloud/ping
401

$ docker --version
Docker version 25.0.0

$ gcc --version
gcc (Ubuntu 15.2.0-16ubuntu1) 15.2.0

Schritt-für-Schritt-Anleitung

01

Schreiben Sie Ihre C-Funktion

Die Binary-Runtime führt Ihr kompiliertes Programm direkt aus. JSON-Ergebnis nach stdout schreiben — das ist der HTTP-Response-Body. Alles auf stderr landet in den Plattform-Logs.

example.c
/*
 * evrtng functions – ANSI C function example
 * Prints a JSON result to stdout (the HTTP response body).
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {

    /* Log to stderr – shows up in the platform logs */
    fprintf(stderr,
        "[evrtng] ANSI C action invoked\n");

    /* The response body */
    printf("{ \"msg\": \"Hello from ANSI C!\" }\n");

    return 0;
}
compile & test locally
# Compile
$ gcc -o example example.c

# Run it — same output your function returns
$ ./example
{ "msg": "Hello from ANSI C!" }
02

Dockerfile erstellen

Kompiliertes Binary in ein minimales Image packen. Die Plattform mountet Ihr Image und führt das Binary aus — kein Runtime-Protokoll nötig.

Dockerfile
# Stage 1 – Build
FROM ubuntu:26.04 AS builder

RUN apt-get update && \
    apt-get install -y gcc libc-dev && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /build
COPY example.c .

# Compile with optimisations and static linking
RUN gcc -O2 -static -o example example.c

# Stage 2 – Runtime (minimal scratch image)
FROM ubuntu:26.04

RUN apt-get update && \
    apt-get install -y libc6 && \
    rm -rf /var/lib/apt/lists/*

COPY --from=builder /build/example /usr/local/bin/example

# The binary runs directly — stdout is the response
ENTRYPOINT ["/usr/local/bin/example"]

Der Multi-Stage-Build hält das finale Image klein. Die Verwendung von -static für das C-Binary macht es vollständig selbstenthalten, sogar auf einem minimalen Base-Image.

03

Docker-Image builden & pushen

Image lokal bauen und in eine öffentlich pullbare Registry pushen. Ersetzen Sie YOUR_DOCKERHUB_USER durch Ihren Docker-Hub-Benutzernamen.

build & push
# Build the image
$ docker build -t YOUR_DOCKERHUB_USER/ansi-c-hello .

Step 1/8 : FROM ubuntu:26.04 AS builder
...
Successfully built a1b2c3d4e5f6
Successfully tagged yourusername/ansi-c-hello:latest

# Log in to Docker Hub
$ docker login

# Push the image
$ docker push YOUR_DOCKERHUB_USER/ansi-c-hello

The push refers to repository [docker.io/yourusername/ansi-c-hello]
latest: digest: sha256:abc123... size: 27.4 MB

# Verify the image is accessible
$ docker pull YOUR_DOCKERHUB_USER/ansi-c-hello
04

Funktion über die API registrieren

Binär-Environment erstellen (einmalig), dann die Funktion aus Ihrem OCI-Image, dann einen HTTP-Trigger. Kein Gateway-Setup — jede Funktion bekommt ihre eigene Tenant-URL.

register via API
# 1. Create a binary environment (once per namespace)
$ curl -X POST $API/v1/namespaces/$NS/environments \
    -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
    -d '{"name": "cenv",
         "image": "ghcr.io/fission/binary-env:1.33.0"}'

# 2. Create the function from your OCI image
$ curl -X POST $API/v1/namespaces/$NS/functions \
    -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
    -d '{"name": "ansi-c", "environment": "cenv",
         "oci_image":
           "YOUR_DOCKERHUB_USER/ansi-c-hello:latest",
         "entrypoint": "example"}'

201 Created

# 3. Add an HTTP trigger
$ curl -X POST $API/v1/namespaces/$NS/triggers \
    -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
    -d '{"name": "ansi-c-http", "function": "ansi-c",
         "type": "http", "url": "/c", "method": "GET"}'
05

Aufrufen & Überwachen

Aufruf über Ihre Tenant-URL. Der erste Aufruf kann bis zu 60 s dauern (Firecracker-Kaltstart); warme Aufrufe antworten in Bruchteilen einer Sekunde.

invoke via tenant URL
# Invoke via your tenant URL
$ curl "https://$NS.fnc4.evrtng.cloud/c" \
    -H "X-API-Key: $KEY"

{ "msg": "Hello from ANSI C!" }
monitor activations & events
# Invocation history via the API
$ curl $API/v1/namespaces/$NS/activations?limit=5 \
    -H "X-API-Key: $KEY"

# Your management actions (audit trail)
$ curl $API/v1/namespaces/$NS/events \
    -H "X-API-Key: $KEY"

JSON mit cJSON parsen

In der Praxis wollen Sie eingehendes JSON parsen. Hier ein vollständigeres Beispiel mit der leichten cJSON-Bibliothek.

action_json.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"   /* cJSON: MIT License */

int main(void) {

    /* Read the request body from stdin */
    char buf[4096] = {0};
    fread(buf, 1, sizeof(buf) - 1, stdin);

    /* Parse input JSON */
    cJSON *input = cJSON_Parse(buf);
    if (!input) {
        printf("{\"error\":\"invalid JSON\"}\n");
        return 1;
    }

    /* Extract "name" field */
    cJSON *name_item = cJSON_GetObjectItem(input, "name");
    const char *name = (name_item && cJSON_IsString(name_item))
        ? name_item->valuestring
        : "World";

    /* Build and output the response */
    cJSON *output = cJSON_CreateObject();
    cJSON_AddStringToObject(output, "message",
        strcat(strcpy(malloc(64), "Hello, "), name));
    cJSON_AddStringToObject(output, "runtime", "ANSI C");

    printf("%s\n", cJSON_Print(output));

    cJSON_Delete(input);
    cJSON_Delete(output);
    return 0;
}

Dockerfile mit cJSON

FROM ubuntu:26.04 AS builder

RUN apt-get update && apt-get install -y \
    gcc libc-dev wget && \
    rm -rf /var/lib/apt/lists/*

# Download cJSON (MIT license)
RUN wget -q \
  https://raw.githubusercontent.com/DaveGamble/cJSON/master/cJSON.c \
  https://raw.githubusercontent.com/DaveGamble/cJSON/master/cJSON.h

WORKDIR /build
COPY action_json.c cJSON.c cJSON.h .

# Compile with cJSON
RUN gcc -O2 -o action action_json.c cJSON.c -lm

FROM ubuntu:26.04
RUN apt-get update && apt-get install -y libc6 && \
    rm -rf /var/lib/apt/lists/*
COPY --from=builder /build/action /usr/local/bin/action
ENTRYPOINT ["/usr/local/bin/action"]
deploy & test
$ docker build -t YOU/ansi-c-json .
$ docker push YOU/ansi-c-json

# Register (once): environment + function + trigger
$ curl -X POST $API/v1/namespaces/$NS/environments \
    -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
    -d '{"name": "cenv", "image": "ghcr.io/fission/binary-env:1.33.0"}'

$ curl -X POST $API/v1/namespaces/$NS/functions \
    -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
    -d '{"name": "cjson", "environment": "cenv",
         "oci_image": "YOU/ansi-c-json:latest"}'

{
  "message": "Hello, evrtng",
  "runtime": "ANSI C"
}

Verwaltung Ihrer C-Action

manage your C function
# Update the function (after rebuild + push)
$ curl -X PUT $API/v1/namespaces/$NS/functions/ansi-c \
    -H "X-API-Key: $KEY" \
    -d '{"oci_image": "USER/ansi-c-hello:v2"}'

# Set memory (validated against your plan)
$ curl -X PUT .../functions/ansi-c \
    -d '{"resources": {"memory": "256Mi"}}'

# Function details (incl. entrypoint, image)
$ curl $API/v1/namespaces/$NS/functions/ansi-c \
    -H "X-API-Key: $KEY"

# Invocation history
$ curl .../activations?limit=5 -H "X-API-Key: $KEY"

# Delete the function
$ curl -X DELETE .../functions/ansi-c \
    -H "X-API-Key: $KEY"
200 OK

Implementierungshinweise

01 Die Binary-Runtime führt Ihr kompiliertes Programm aus und gibt dessen stdout als HTTP-Response-Body zurück.
02 Der Output muss gültiges JSON auf stdout sein. Alles auf stderr erscheint in den Aktivierungs-Logs (für Debugging verwenden).
03 Das Docker-Image muss öffentlich zugänglich sein oder in einer Registry gehostet werden, die mit evrtng functions konfiguriert ist.
04 Kompilieren Sie aus Sicherheitsgründen mit -fstack-protector-strong und validieren Sie alle Eingaben vor der Verwendung.
05 Wenn Sie Shared Libraries (openssl, curl etc.) benötigen, linken Sie diese statisch oder installieren Sie sie im Docker-Image.
06 cJSON (MIT-Lizenz) ist eine sichere Wahl für die JSON-Verarbeitung in C. libjansson und yyjson sind ebenfalls gute Alternativen.

Nächste Schritte