calog/examples/staticDemo.c

112 lines
3.6 KiB
C

// staticDemo.c -- a self-contained calog application, built as a fully static binary.
//
// It embeds the Lua engine, the DB library (SQLite backend), and the network library, then
// runs one script that sums 1..10 through an in-memory database and opens/closes a UDP
// socket -- proving the engine, DB, and network stacks all work in a `-static` executable
// with no shared-library dependencies at runtime. Build it with `make static`.
//
// Static-glibc caveat: name resolution (getaddrinfo) and dlopen-based Lua C modules do not
// work in a fully static glibc binary -- connect by IP and avoid `require` of C modules, or
// link musl. This demo uses neither, so it is fully self-contained.
#define _POSIX_C_SOURCE 200809L
#include "calog.h"
#include "calogDb.h"
#include "calogNet.h"
#include <stdatomic.h>
#include <stdio.h>
#include <time.h>
static _Atomic int64_t reportedTotal = -1;
static _Atomic bool scriptDone = false;
static _Atomic int32_t errorCount = 0;
static int32_t nativeDone(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
(void)args;
(void)argCount;
(void)userData;
atomic_store(&scriptDone, true);
calogValueNil(result);
return calogOkE;
}
static int32_t nativeReport(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
(void)userData;
calogValueNil(result);
if (argCount != 1 || args[0].type != calogIntE) {
return calogFail(result, calogErrArgE, "report expects one integer");
}
atomic_store(&reportedTotal, args[0].as.i);
return calogOkE;
}
static void onError(uint64_t contextId, const char *message, void *userData) {
(void)contextId;
(void)userData;
fprintf(stderr, "script error: %s\n", (message != NULL) ? message : "(null)");
atomic_fetch_add(&errorCount, 1);
}
int main(void) {
CalogT *calog;
CalogContextT *ctx;
struct timespec tick = { 0, 1000000 };
int i;
calog = calogCreate();
if (calog == NULL) {
printf("calog create failed\n");
return 1;
}
calogSetErrorHandler(calog, onError, NULL);
calogRegister(calog, "report", nativeReport, NULL);
calogRegister(calog, "done", nativeDone, NULL);
if (calogDbRegister(calog) != calogOkE || calogNetRegister(calog) != calogOkE) {
printf("library registration failed\n");
return 1;
}
ctx = calogContextOpen(calog, &calogLuaEngine);
if (ctx == NULL) {
printf("context open failed\n");
calogDestroy(calog);
calogDbShutdown();
calogNetShutdown();
return 1;
}
calogContextEval(ctx,
"local db = dbOpen('sqlite', ':memory:')\n"
"dbExec(db, 'create table n (v integer)')\n"
"for i = 1, 10 do dbExec(db, 'insert into n values (?)', i) end\n"
"local rows = dbQuery(db, 'select sum(v) as total from n')\n"
"local total = rows[1].total\n"
"dbClose(db)\n"
"local s = udpOpen(0)\n"
"udpClose(s)\n"
"report(total)\n"
"done()");
for (i = 0; i < 2000 && !atomic_load(&scriptDone) && atomic_load(&errorCount) == 0; i++) {
calogPump(calog);
nanosleep(&tick, NULL);
}
calogPump(calog);
calogContextClose(ctx);
calogDestroy(calog);
calogDbShutdown();
calogNetShutdown();
if (atomic_load(&reportedTotal) != 55) {
printf("FAILED: expected 55, got %lld\n", (long long)atomic_load(&reportedTotal));
return 1;
}
printf("static calog app OK: SQLite summed 1..10 = %lld, UDP socket opened + closed\n", (long long)atomic_load(&reportedTotal));
return 0;
}