libipc/examples/pongd-with-c-bindings.zig
Philippe Pittoli 76e3144436 Ready for Zig v0.15.2. Details in commit message.
The library jumped to Zig v0.15.2 which implies a new build system.
`build.zig` now compiles libipc as both static and dynamic libraries,
and provides an entry point to use `libipc` as-is for Zig applications.

Some examples have been added to help new users play with the library.

Thanks to these fairly complete examples, two (very small) leaks related
to sentinel values (in arrays containing paths) were fixed.
2025-10-25 16:35:02 +02:00

100 lines
3.7 KiB
Zig

// Example of a `pong` service using the C bindings.
const std = @import("std");
// Only bindings are available.
const libipc = @cImport({
@cInclude("../../../libipc.h");
});
const SERVICE = "pong";
const SERVICE_LEN = 4;
const MAX_MSG_SIZE = 10000;
pub fn main() !u8 {
var ctx : *anyopaque = undefined;
var ret : c_int = 0;
var servicefd : c_int = undefined;
var buffer : [MAX_MSG_SIZE]u8 = undefined;
var size : usize = MAX_MSG_SIZE;
var event_type : u8 = undefined;
var index : usize = 0;
var originfd : c_int = undefined;
std.debug.print("Init context.\n", .{});
ret = libipc.ipc_context_init (@ptrCast(&ctx));
if (ret != 0) {
std.debug.print("Cannot init context.\n", .{});
return 1;
}
defer {
std.debug.print("Deinit context.\n", .{});
libipc.ipc_context_deinit (@ptrCast(&ctx));
}
std.debug.print ("Create the 'pong' service.\n", .{});
ret = libipc.ipc_service_init (ctx, &servicefd, SERVICE, SERVICE_LEN);
if (ret != 0) {
std.debug.print("Cannot create the service.\n", .{});
return 1;
}
std.debug.print ("Listening to the standard input (press enter to quit).\n", .{});
ret = libipc.ipc_add_external (ctx, 0);
if (ret != 0) {
std.debug.print ("Cannot listen to standard input.", .{});
return 1;
}
std.debug.print("Set the timer to two seconds.\n", .{});
libipc.ipc_context_timer (ctx, 2000);
var event_count : u32 = 0;
std.debug.print("Let's loop over events.\n", .{});
while(true) {
size = MAX_MSG_SIZE;
var newfd : c_int = undefined;
const pbuffer : [*c]u8 = &buffer;
ret = libipc.ipc_wait_event (ctx, &event_type, &index, &originfd, &newfd, pbuffer, &size);
if (ret != 0) {
std.debug.print("Error while waiting for an event.", .{});
return 1;
}
event_count += 1;
switch (event_type) {
libipc.ERROR => { std.debug.print("Error.", .{}); return 1; },
libipc.EXTERNAL => { std.debug.print("Quitting.\n", .{}); return 0; },
libipc.SWITCH_RX => { std.debug.print("Switch RX (shouldn't happen).", .{}); return 1; },
libipc.SWITCH_TX => { std.debug.print("Switch TX (shouldn't happen).", .{}); return 1; },
libipc.CONNECTION => { std.debug.print("Connection (fd {d}).\n", .{newfd}); },
libipc.DISCONNECTION => { std.debug.print("Disconnection (fd {d}).\n", .{originfd}); },
libipc.TIMER => { std.debug.print("\rTIMER ({d}).\r", .{event_count}); },
libipc.MESSAGE_TX => { std.debug.print("A message has been sent.\n", .{}); },
libipc.MESSAGE_RX => {
if (size == 0) {
std.debug.print("No message returned.\n", .{});
return 1;
}
buffer[size] = 0;
std.debug.print("Message from {d} (size {d}): {s}.\n", .{ originfd, size, buffer[0..size] });
std.debug.print ("Schedule a message for {d}.\n", .{originfd});
ret = libipc.ipc_schedule (ctx, originfd, pbuffer, size);
if (ret != 0) {
std.debug.print("Cannot schedule a message.\n", .{});
return 1;
}
},
else => { std.debug.print("Unknown IPC message type.\n", .{}); return 1; },
}
}
return 0;
}