Skip to content

Commit

Permalink
Change to using libzmq
Browse files Browse the repository at this point in the history
(instead of czmq)
  • Loading branch information
fkollmann committed Mar 10, 2024
1 parent cda2944 commit 518f159
Show file tree
Hide file tree
Showing 13 changed files with 835 additions and 341 deletions.
42 changes: 27 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

This Zig library provides a ZeroMQ client.

It is implemented as a wrapper of the "High-level C Binding for ZeroMQ" ([CZMQ](http://czmq.zeromq.org)).
It is implemented based on the C API of [libzmq](https://libzmq.readthedocs.io/en/latest/).
The interface is highly inspired by [CZMQ](http://czmq.zeromq.org) and [goczmq](https://github.com/zeromq/goczmq).

It was originally based on the "High-level C Binding for ZeroMQ" ([CZMQ](http://czmq.zeromq.org)),
but later moved to using [libzmq](https://libzmq.readthedocs.io/en/latest/) directly, to provide zero-copy message support.

**IMPORTANT: The library is currently still work in progress!!**

Expand All @@ -12,7 +16,7 @@ It is implemented as a wrapper of the "High-level C Binding for ZeroMQ" ([CZMQ](

### Minimal Example

Since this library is basically a 1:1 wrapper of CZMQ, please refer to the [CZMQ documentation](http://czmq.zeromq.org) to get a better understanding on how the library works.
This repository holds various example within the `examples` folder.
Please feel free to also have a look at the various unit tests in this library (esp. [ZSocket](src/classes/zsocket.zig)).

Running the server (also see [full example](https://github.com/nine-lives-later/zzmq/tree/main/examples/hello_world_server)):
Expand All @@ -23,20 +27,26 @@ const zzmq = @import("zzmq");
var socket = try zzmq.ZSocket.init(allocator, zzmq.ZSocketType.Pair);
defer socket.deinit();
const port = try socket.bind("tcp://127.0.0.1:!");
try socket.bind("tcp://127.0.0.1:*");
std.log.info("Endpoint: {s}", .{try socket.endpoint()});
// send a message
var frame = try zzmq.ZFrame.init(data);
defer frame.deinit();
var message = try zzmq.ZMessage.initUnmanaged(data, null);
defer message.deinit();
try socket.send(&frame, .{});
try socket.send(&message, .{});
```

Running the client (also see [full example](https://github.com/nine-lives-later/zzmq/tree/main/examples/hello_world_client)):

```zig
const zzmq = @import("zzmq");
var socket = try zzmq.ZSocket.init(allocator, zzmq.ZSocketType.Pair);
var context = try zzmq.ZContext.init(allocator);
defer context.deinit();
var socket = try zzmq.ZSocket.init(zzmq.ZSocketType.Pair, &context);
defer socket.deinit();
const endpoint = try std.fmt.allocPrint(allocator, "tcp://127.0.0.1:{}", .{port});
Expand All @@ -45,10 +55,10 @@ defer allocator.free(endpoint);
try socket.connect(endpoint);
// receive a message
var frame = try socket.receive();
defer frame.deinit();
var message = try socket.receive(.{});
defer message.deinit();
const data = try frame.data();
const data = try message.data();
```


Expand Down Expand Up @@ -83,24 +93,26 @@ const zzmq = b.dependency("zzmq", .{
// `exe.root_module.addImport` instead of `exe.addModule`
exe.addModule("zzmq", zzmq.module("zzmq"));
exe.linkSystemLibrary("czmq");
exe.linkSystemLibrary("zmq");
exe.linkLibC();
```

### Installing local dependencies

Installing [CZMQ](http://czmq.zeromq.org) development library version 4.0 or higher is also required:
Installing [libzmq](https://zeromq.org/download/) development library version 4.1 or higher is also required:

```sh
# Building on Ubuntu, PoP_OS, ZorinOS, etc.
sudo apt install libczmq-dev
sudo apt install libzmq5-dev

# Running on Ubuntu, PoP_OS, ZorinOS, etc.
sudo apt install libczmq
sudo apt install libzmq5
```

See the [unit test Dockerfile](test.Dockerfile) on how to install it into an Alpine Docker image.

To retrieve the version of the libzmq library actually being used, call `ZContext.version()`.

## Contributing

### Zig Version Branches
Expand All @@ -121,7 +133,7 @@ The library can be tested locally by running: `zig build test`.

Implementation done by [Felix Kollmann](https://github.com/fkollmann).

Based on the work of [CZMQ](http://czmq.zeromq.org), inspired by [goczmq](https://github.com/zeromq/goczmq).
Inspired by [CZMQ](http://czmq.zeromq.org) and [goczmq](https://github.com/zeromq/goczmq).

## License

Expand Down
2 changes: 1 addition & 1 deletion build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub fn build(b: *std.Build) !void {
.optimize = optimize,
});

lib_test.linkSystemLibrary("czmq");
lib_test.linkSystemLibrary("zmq");
lib_test.linkLibC();

const run_test = b.addRunArtifact(lib_test);
Expand Down
2 changes: 2 additions & 0 deletions build_and_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@
set -e

zig build test --summary all
#zig test src/zzmq.zig -lc -lzmq

zig fmt . > /dev/null
1 change: 1 addition & 0 deletions libzmq/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
output/
20 changes: 20 additions & 0 deletions libzmq/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM alpine:3.19 as builder

RUN apk add --no-cache g++ gcc cmake make musl-dev

# add the pre-processed source package (note: this is not the raw source code from Git!)
ADD https://github.com/zeromq/libzmq/releases/download/v4.3.5/zeromq-4.3.5.tar.gz /tmp/source.tgz

WORKDIR /build

RUN tar -xzf /tmp/source.tgz --strip-components=1

RUN ./configure --prefix=/build/output
RUN make install



# copy the build output
FROM alpine:3.19

COPY --from=builder /build/output /build/output
15 changes: 15 additions & 0 deletions libzmq/build_and_extract.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/sh

set -e

IMAGE=zzmq_libzmq_345345345

DOCKER_BUILDKIT=1 docker build . -t $IMAGE

if [ -d output ]; then
rm -rf output
fi

mkdir -p output

docker run -v "$PWD/output:/mnt" $IMAGE sh -c "cp -rf /build/output/* /mnt/ && chown $(id -u):$(id -g) -R /mnt/"
79 changes: 79 additions & 0 deletions src/classes/zcontext.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
const std = @import("std");
const c = @import("../zmq.zig").c;

/// Version information of the `libzmq` in use.
pub const ZVersion = struct {
major: u16,
minor: u16,
patch: u16,
};

/// Creates a new ZermoMQ context.
///
/// Multiple contextes can exist independently, e.g. for libraries.
///
/// A 0MQ 'context' is thread safe and may be shared among as many application threads as necessary,
/// without any additional locking required on the part of the caller.
pub const ZContext = struct {
allocator_: std.mem.Allocator,
ctx_: *anyopaque,

pub fn init(allocator: std.mem.Allocator) !ZContext {
// check the libzmq version 4.x
if (ZContext.version().major != 4) {
return error.LibZmqVersionMismatch;
}

// try creating the socket, early
var s = c.zmq_ctx_new() orelse {
switch (c.zmq_errno()) {
c.EMFILE => return error.MaxOpenFilesExceeded,
else => return error.ContextCreateFailed,
}
};
errdefer {
c.zmq_ctx_term(s);
}

// done
return .{
.allocator_ = allocator,
.ctx_ = s,
};
}

/// Destroy the socket and clean up
pub fn deinit(self: *ZContext) void {
_ = c.zmq_ctx_term(self.ctx_);
}

/// Returns the version of the `libzmq` shared library.
pub fn version() ZVersion {
var major: c_int = undefined;
var minor: c_int = undefined;
var patch: c_int = undefined;

c.zmq_version(&major, &minor, &patch);

return .{
.major = @intCast(major),
.minor = @intCast(minor),
.patch = @intCast(patch),
};
}
};

test "ZContext - roundtrip" {
const allocator = std.testing.allocator;

var incoming = try ZContext.init(allocator);
defer incoming.deinit();
}

test "ZContext - version" {
const v = ZContext.version();

std.log.info("Version: {}.{}.{}", .{ v.major, v.minor, v.patch });

try std.testing.expectEqual(@as(u16, 4), v.major);
}
127 changes: 0 additions & 127 deletions src/classes/zframe.zig

This file was deleted.

Loading

0 comments on commit 518f159

Please sign in to comment.