From 16fd65e281776bd27d9aefdcfb39fa8b8f7a9fba Mon Sep 17 00:00:00 2001 From: Robby Zambito Date: Sat, 24 Jan 2026 16:13:35 -0500 Subject: Add C API --- src/Connection.zig | 4 +++ src/c_api.zig | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.zig | 1 + 3 files changed, 94 insertions(+) create mode 100644 src/c_api.zig (limited to 'src') diff --git a/src/Connection.zig b/src/Connection.zig index 95805de..cdeb57e 100644 --- a/src/Connection.zig +++ b/src/Connection.zig @@ -12,6 +12,10 @@ pub fn init(socket: RawSocket, headers: EthIpUdp, connection: SaprusMessage) Con }; } +pub fn deinit(self: *Connection) void { + self.socket.deinit(); +} + pub fn next(self: Connection, io: Io, buf: []u8) ![]const u8 { _ = io; log.debug("Awaiting connection message", .{}); diff --git a/src/c_api.zig b/src/c_api.zig new file mode 100644 index 0000000..8f861b9 --- /dev/null +++ b/src/c_api.zig @@ -0,0 +1,89 @@ +const std = @import("std"); +const zaprus = @import("zaprus"); + +// Opaque types for C API +const ZaprusClient = opaque {}; +const ZaprusConnection = opaque {}; + +const alloc = std.heap.c_allocator; +const io = std.Io.Threaded.global_single_threaded.io(); + +export fn zaprus_init_client() ?*ZaprusClient { + const client = alloc.create(zaprus.Client) catch return null; + client.* = zaprus.Client.init() catch { + alloc.destroy(client); + return null; + }; + return @ptrCast(client); +} + +export fn zaprus_deinit_client(client: ?*ZaprusClient) void { + const c: ?*zaprus.Client = @ptrCast(@alignCast(client)); + if (c) |zc| { + zc.deinit(); + alloc.destroy(zc); + } +} + +export fn zaprus_client_send_relay( + client: ?*ZaprusClient, + payload: [*c]const u8, + payload_len: usize, + dest: [*c]const u8, +) c_int { + const c: ?*zaprus.Client = @ptrCast(@alignCast(client)); + const zc = c orelse return 1; + + zc.sendRelay(io, payload[0..payload_len], dest[0..4].*) catch return 1; + return 0; +} + +export fn zaprus_connect( + client: ?*ZaprusClient, + payload: [*c]const u8, + payload_len: usize, +) ?*ZaprusConnection { + const c: ?*zaprus.Client = @ptrCast(@alignCast(client)); + const zc = c orelse return null; + + const connection = alloc.create(zaprus.Connection) catch return null; + connection.* = zc.connect(io, payload[0..payload_len]) catch { + alloc.destroy(connection); + return null; + }; + return @ptrCast(connection); +} + +export fn zaprus_deinit_connection(connection: ?*ZaprusConnection) void { + const c: ?*zaprus.Connection = @ptrCast(@alignCast(connection)); + if (c) |zc| { + zc.deinit(); + alloc.destroy(zc); + } +} + +export fn zaprus_connection_next( + connection: ?*ZaprusConnection, + out: [*c]u8, + capacity: usize, + out_len: *usize, +) c_int { + const c: ?*zaprus.Connection = @ptrCast(@alignCast(connection)); + const zc = c orelse return 1; + + const result = zc.next(io, out[0..capacity]) catch return 1; + out_len.* = result.len; + return 0; +} + +export fn zaprus_connection_send( + connection: ?*ZaprusConnection, + payload: [*c]const u8, + payload_len: usize, +) c_int { + const c: ?*zaprus.Connection = @ptrCast(@alignCast(connection)); + const zc = c orelse return 1; + + zc.send(io, payload[0..payload_len]) catch return 1; + return 0; +} diff --git a/src/main.zig b/src/main.zig index 3fcdeda..2cbcb24 100644 --- a/src/main.zig +++ b/src/main.zig @@ -134,6 +134,7 @@ pub fn main(init: std.process.Init) !void { var w: Writer = .fixed(&init_con_buf); try w.print("{b64}", .{flags.connect.?}); var connection = try client.connect(init.io, w.buffered()); + defer connection.deinit(); log.debug("Connection started", .{}); -- cgit