Add pong example with c bindings.
This commit is contained in:
parent
6743fc66a0
commit
4273f96573
4 changed files with 104 additions and 30 deletions
14
build.zig
14
build.zig
|
|
@ -71,13 +71,13 @@ pub fn build(b: *std.Build) void {
|
|||
b.installArtifact(lib_dynamic_c);
|
||||
|
||||
// pong service using the c client.
|
||||
const c_pong = b.addExecutable(.{
|
||||
.name = "ping", // name of the executable
|
||||
const pong_with_c_bindings = b.addExecutable(.{
|
||||
.name = "pong-with-c-bindings", // name of the executable
|
||||
.root_module = b.createModule(.{
|
||||
// b.createModule defines a new module just like b.addModule but,
|
||||
// unlike b.addModule, it does not expose the module to consumers of
|
||||
// this package, which is why in this case we don't have to give it a name.
|
||||
.root_source_file = b.path("src/examples/c_pong.zig"),
|
||||
.root_source_file = b.path("src/examples/pong-with-c-bindings.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
// List of modules available for import in source files part of the
|
||||
|
|
@ -97,10 +97,10 @@ pub fn build(b: *std.Build) void {
|
|||
// install prefix when running `zig build` (i.e. when executing the default
|
||||
// step). By default the install prefix is `zig-out/` but can be overridden
|
||||
// by passing `--prefix` or `-p`.
|
||||
b.installArtifact(c_pong);
|
||||
b.installArtifact(pong_with_c_bindings);
|
||||
|
||||
// Link the executable to the library.
|
||||
c_pong.linkLibrary(lib_static_c);
|
||||
pong_with_c_bindings.linkLibrary(lib_static_c);
|
||||
|
||||
// This creates a top level step. Top level steps have a name and can be
|
||||
// invoked by name when running `zig build` (e.g. `zig build run`).
|
||||
|
|
@ -115,7 +115,7 @@ pub fn build(b: *std.Build) void {
|
|||
// or if another step depends on it, so it's up to you to define when and
|
||||
// how this Run step will be executed. In our case we want to run it when
|
||||
// the user runs `zig build run`, so we create a dependency link.
|
||||
const run_cmd = b.addRunArtifact(c_pong);
|
||||
const run_cmd = b.addRunArtifact(pong_with_c_bindings);
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
|
||||
// By making the run step depend on the default step, it will be run from the
|
||||
|
|
@ -142,7 +142,7 @@ pub fn build(b: *std.Build) void {
|
|||
// root module. Note that test executables only test one module at a time,
|
||||
// hence why we have to create two separate ones.
|
||||
const exe_tests = b.addTest(.{
|
||||
.root_module = c_pong.root_module,
|
||||
.root_module = pong_with_c_bindings.root_module,
|
||||
});
|
||||
|
||||
// A run step that will run the second test executable.
|
||||
|
|
|
|||
1
libipc.h
1
libipc.h
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef LIBIPC
|
||||
#define LIBIPC
|
||||
|
||||
#include <stdio.h> // Required to have types such as `size_t`.
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
// Example of a `pong` client using the C bindings.
|
||||
const std = @import("std");
|
||||
|
||||
// Only bindings are available.
|
||||
const libipc = @cImport({
|
||||
@cInclude("stdio.h"); // Required to have types such as `size_t`.
|
||||
@cInclude("../../../libipc.h");
|
||||
});
|
||||
|
||||
const service_name = "pong";
|
||||
|
||||
pub fn main() !void {
|
||||
// Prints to stderr, ignoring potential errors.
|
||||
std.debug.print("{s} service.\n", .{service_name});
|
||||
var ctx : *anyopaque = undefined;
|
||||
var ret : c_int = 0;
|
||||
ret = libipc.ipc_context_init (@ptrCast(&ctx));
|
||||
|
||||
if (ret != 0) {
|
||||
std.debug.print("oops\n", .{});
|
||||
return;
|
||||
}
|
||||
}
|
||||
96
src/examples/pong-with-c-bindings.zig
Normal file
96
src/examples/pong-with-c-bindings.zig
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
// Example of a `pong` client 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 ("Connect to a 'pong' service.\n", .{});
|
||||
ret = libipc.ipc_connect_service (ctx, &servicefd, SERVICE, SERVICE_LEN);
|
||||
|
||||
if (ret != 0) {
|
||||
std.debug.print("Cannot connect to a service.\n", .{});
|
||||
return 1;
|
||||
}
|
||||
|
||||
std.debug.print ("Let's schedule a message.\n", .{});
|
||||
ret = libipc.ipc_schedule (ctx, servicefd, "hello, plz bounce me", 21);
|
||||
|
||||
if (ret != 0) {
|
||||
std.debug.print("Cannot schedule a message.\n", .{});
|
||||
return 1;
|
||||
}
|
||||
|
||||
std.debug.print("Let's set the timer to one second.\n", .{});
|
||||
libipc.ipc_context_timer (ctx, 1000);
|
||||
|
||||
var should_continue : bool = true;
|
||||
var event_count : u32 = 0;
|
||||
|
||||
std.debug.print("Let's loop over events.\n", .{});
|
||||
while(should_continue) {
|
||||
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;
|
||||
std.debug.print("EVENT n°{d} type {d}\t", .{ event_count, event_type });
|
||||
|
||||
switch (event_type) {
|
||||
libipc.ERROR => { std.debug.print("Error.", .{}); return 1; },
|
||||
libipc.EXTERNAL => { std.debug.print("External (shouldn't happen).", .{}); return 1; },
|
||||
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 (shouldn't happen).", .{}); return 1; },
|
||||
libipc.DISCONNECTION => { std.debug.print("Disconnection (shouldn't happen).", .{}); return 1; },
|
||||
libipc.TIMER => { std.debug.print("TIMER.\n", .{}); },
|
||||
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("Response (size {d}): {s}.\n", .{ size, buffer });
|
||||
// We received the response, quitting.
|
||||
should_continue = false;
|
||||
},
|
||||
else => { std.debug.print("Unknown IPC message type.\n", .{}); return 1; },
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue