feat(zmq): Simplified bindings.

This commit is contained in:
2026-07-08 12:37:26 -04:00
parent 7e261b2a5d
commit ad43577b44
4 changed files with 66 additions and 45 deletions
+1
View File
@@ -1,3 +1,4 @@
.direnv .direnv
node_modules node_modules
vendor vendor
zmq_odin
+7 -7
View File
@@ -31,7 +31,7 @@ main :: proc() {
req, cerr := zmq.socket(ctx, .REQ) req, cerr := zmq.socket(ctx, .REQ)
if cerr != nil { if cerr != nil {
log.panic(zmq.strerror(cerr)) log.panicf("err: %v (%d) %s", cerr, cerr, zmq.strerror(cerr))
} }
defer zmq.close(req) defer zmq.close(req)
if err := zmq.connect(req, "inproc://echo"); err != nil { if err := zmq.connect(req, "inproc://echo"); err != nil {
@@ -41,7 +41,7 @@ main :: proc() {
echo(req, rep) echo(req, rep)
} }
echo :: proc(req, rep: zmq.Socket) { echo :: proc(client, server: zmq.Socket) {
scanner: bufio.Scanner scanner: bufio.Scanner
bufio.scanner_init(&scanner, os.to_reader(os.stdin)) bufio.scanner_init(&scanner, os.to_reader(os.stdin))
defer bufio.scanner_destroy(&scanner) defer bufio.scanner_destroy(&scanner)
@@ -52,20 +52,20 @@ echo :: proc(req, rep: zmq.Socket) {
if len(line) == 0 { if len(line) == 0 {
continue continue
} }
if _, err := zmq.send(req, transmute([]u8)line); err != nil { if _, err := zmq.send(client, line); err != nil {
fmt.eprintfln("send: %s", zmq.strerror(err)) fmt.eprintfln("send: %s", zmq.strerror(err))
return return
} }
n, rerr := zmq.recv(rep, buf[:]) n, rerr := zmq.recv(server, buf[:])
if rerr != nil { if rerr != nil {
fmt.eprintfln("rep recv: %s", zmq.strerror(rerr)) fmt.eprintfln("rep recv: %s", zmq.strerror(rerr))
return return
} }
if _, werr := zmq.send(rep, buf[:n]); werr != nil { if _, werr := zmq.send(server, buf[:n]); werr != nil {
fmt.eprintfln("rep send: %s", zmq.strerror(werr)) fmt.eprintfln("rep send: %v %s", werr, zmq.strerror(werr))
return return
} }
m, qerr := zmq.recv(req, buf[:]) m, qerr := zmq.recv(client, buf[:])
if qerr != nil { if qerr != nil {
fmt.eprintfln("req recv: %s", zmq.strerror(qerr)) fmt.eprintfln("req recv: %s", zmq.strerror(qerr))
return return
+45 -38
View File
@@ -6,35 +6,35 @@ import "core:strings"
foreign import lib "system:zmq" foreign import lib "system:zmq"
@(default_calling_convention = "c") Context :: distinct rawptr
Socket :: distinct rawptr
@(default_calling_convention = "c", link_prefix = "zmq_")
foreign lib { foreign lib {
@(link_name = "zmq_ctx_new") // TODO: Try to access errno directly
_ctx_new :: proc() -> rawptr --- errno :: proc() -> c.int ---
ctx_new :: proc() -> Context ---
@(link_name = "zmq_ctx_term") @(link_name = "zmq_ctx_term")
_ctx_term :: proc(ctx: rawptr) -> c.int --- _ctx_term :: proc(ctx: Context) -> c.int ---
@(link_name = "zmq_socket") @(link_name = "zmq_socket")
_socket :: proc(ctx: rawptr, type: Socket_Type) -> rawptr --- _socket :: proc(ctx: Context, type: Socket_Type) -> Socket ---
@(link_name = "zmq_close") @(link_name = "zmq_close")
_close :: proc(s: rawptr) -> c.int --- _close :: proc(s: Socket) -> c.int ---
@(link_name = "zmq_bind") @(link_name = "zmq_bind")
_bind :: proc(s: rawptr, addr: cstring) -> c.int --- _bind :: proc(s: Socket, addr: cstring) -> c.int ---
@(link_name = "zmq_connect") @(link_name = "zmq_connect")
_connect :: proc(s: rawptr, addr: cstring) -> c.int --- _connect :: proc(s: Socket, addr: cstring) -> c.int ---
@(link_name = "zmq_send") @(link_name = "zmq_send")
_send :: proc(s: rawptr, buf: rawptr, len: c.size_t, flags: c.int) -> c.int --- _send :: proc(s: Socket, buf: rawptr, len: c.size_t, flags: Flags) -> c.int ---
@(link_name = "zmq_recv") @(link_name = "zmq_recv")
_recv :: proc(s: rawptr, buf: rawptr, len: c.size_t, flags: c.int) -> c.int --- _recv :: proc(s: Socket, buf: rawptr, len: c.size_t, flags: Flags) -> c.int ---
@(link_name = "zmq_errno")
_errno :: proc() -> c.int ---
@(link_name = "zmq_strerror") @(link_name = "zmq_strerror")
_strerror :: proc(errnum: c.int) -> cstring --- _strerror :: proc(errnum: c.int) -> cstring ---
@(link_name = "zmq_version") @(link_name = "zmq_version")
_version :: proc(major, minor, patch: ^c.int) --- _version :: proc(major, minor, patch: ^c.int) ---
} }
Context :: distinct rawptr
Socket :: distinct rawptr
Socket_Type :: enum c.int { Socket_Type :: enum c.int {
PAIR = 0, PAIR = 0,
PUB = 1, PUB = 1,
@@ -73,23 +73,23 @@ Error :: union #shared_nil {
ZMQ_Error, ZMQ_Error,
} }
from_errno :: proc(raw: c.int) -> Error { last_error :: proc() -> Error {
raw := errno()
if raw >= HAUSNUMERO { if raw >= HAUSNUMERO {
return ZMQ_Error(raw) return ZMQ_Error(raw)
} }
return os.Platform_Error(raw) return os.Platform_Error(raw)
} }
last_error :: proc() -> Error {return from_errno(_errno())} strerror :: proc(e: Error) -> cstring {
strerror :: proc(e: Error) -> string {
switch v in e { switch v in e {
case os.Platform_Error: case os.Platform_Error:
return string(_strerror(c.int(v))) return _strerror(c.int(v))
case ZMQ_Error: case ZMQ_Error:
return string(_strerror(c.int(v))) return _strerror(c.int(v))
case: case:
return "" return _strerror(0)
} }
} }
@@ -99,46 +99,53 @@ version :: proc() -> (major, minor, patch: int) {
return int(ma), int(mi), int(pa) return int(ma), int(mi), int(pa)
} }
ctx_new :: proc() -> Context {
return Context(_ctx_new())
}
ctx_term :: proc(ctx: Context) -> Error { ctx_term :: proc(ctx: Context) -> Error {
return _ctx_term(rawptr(ctx)) == 0 ? nil : last_error() return _ctx_term(ctx) == 0 ? nil : last_error()
} }
socket :: proc(ctx: Context, type: Socket_Type) -> (Socket, Error) { socket :: proc(ctx: Context, type: Socket_Type) -> (s: Socket, err: Error) {
s := _socket(rawptr(ctx), type) s = _socket(ctx, type)
if s == nil { if s == nil {
return nil, last_error() err = last_error()
} }
return Socket(s), nil
return s, err
} }
close :: proc(s: Socket) -> Error { close :: proc(s: Socket) -> Error {
return _close(rawptr(s)) == 0 ? nil : last_error() return _close(s) == 0 ? nil : last_error()
} }
bind :: proc(s: Socket, addr: string, allocator := context.temp_allocator) -> Error { bind :: proc(s: Socket, addr: string, allocator := context.temp_allocator) -> Error {
c := strings.clone_to_cstring(addr, allocator) c := strings.clone_to_cstring(addr, allocator)
return _bind(rawptr(s), c) == 0 ? nil : last_error() return _bind(s, c) == 0 ? nil : last_error()
} }
connect :: proc(s: Socket, addr: string, allocator := context.temp_allocator) -> Error { connect :: proc(s: Socket, addr: string, allocator := context.temp_allocator) -> Error {
c := strings.clone_to_cstring(addr, allocator) c := strings.clone_to_cstring(addr, allocator)
return _connect(rawptr(s), c) == 0 ? nil : last_error() return _connect(s, c) == 0 ? nil : last_error()
} }
send :: proc(s: Socket, buf: []u8, flags: Flags = Flags{}) -> (int, Error) { send :: proc {
n := _send(rawptr(s), rawptr(&buf[0]), c.size_t(len(buf)), transmute(c.int)flags) send_bytes,
send_string,
}
send_bytes :: proc(s: Socket, buf: []u8, flags: Flags = Flags{}) -> (int, Error) {
n := _send(s, rawptr(&buf[0]), c.size_t(len(buf)), flags)
if n < 0 { if n < 0 {
return -1, last_error() return -1, last_error()
} }
return int(n), nil return int(n), Error{}
}
send_string :: proc(s: Socket, buf: string, flags: Flags = Flags{}) -> (int, Error) {
return send_bytes(s, transmute([]u8)buf, flags)
} }
recv :: proc(s: Socket, buf: []u8, flags: Flags = Flags{}) -> (int, Error) { recv :: proc(s: Socket, buf: []u8, flags: Flags = Flags{}) -> (int, Error) {
n := _recv(rawptr(s), rawptr(&buf[0]), c.size_t(len(buf)), transmute(c.int)flags) n := _recv(s, rawptr(&buf[0]), c.size_t(len(buf)), flags)
if n < 0 { if n < 0 {
return -1, last_error() return -1, last_error()
} }
+13
View File
@@ -0,0 +1,13 @@
#+test
package zmq
import "core:testing"
@(test)
test_error_type :: proc(t: ^testing.T) {
e: Error = .EFSM
testing.expect_value(t, size_of(e), 8)
}