112 lines
3.6 KiB
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;
|
|
}
|