mirror of
https://github.com/sbrow/zomq.git
synced 2026-08-26 10:53:32 -04:00
fix(zmq): Corrected error bindings.
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
package main
|
||||
|
||||
import "core:fmt"
|
||||
import "core:os"
|
||||
import "zmq"
|
||||
|
||||
main :: proc() {
|
||||
ctx := zmq.ctx_new()
|
||||
defer zmq.ctx_term(ctx)
|
||||
|
||||
rep1, _ := zmq.socket(ctx, .REP)
|
||||
defer zmq.close(rep1)
|
||||
zmq.bind(rep1, "tcp://*:5555")
|
||||
|
||||
rep2, _ := zmq.socket(ctx, .REP)
|
||||
defer zmq.close(rep2)
|
||||
if err := zmq.bind(rep2, "tcp://*:5555"); err != nil {
|
||||
fmt.eprintfln("bind failed: %s", zmq.strerror(err))
|
||||
switch e in err {
|
||||
case zmq.ZMQ_Error:
|
||||
fmt.eprintfln(" variant: ZMQ_Error, member: %v", e)
|
||||
case os.Platform_Error:
|
||||
fmt.eprintfln(" variant: Platform_Error, member: %v", e)
|
||||
case:
|
||||
fmt.eprintfln(" variant: nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
package zmq
|
||||
|
||||
import "core:c"
|
||||
import "core:os"
|
||||
|
||||
// ZMQ_HAUSNUMERO — base offset for ZMQ's private error codes.
|
||||
//
|
||||
// zmq.h defines two ranges on top of this base:
|
||||
// +1..18 — fallback POSIX errnos (ENOTSUP, EPROTONOSUPPORT, ... ENETRESET).
|
||||
// Only used when the platform's C <errno.h> lacks the symbol
|
||||
// (e.g. MSVC on Windows). On Linux/macOS the system's native
|
||||
// errno values are used instead, so these never appear from
|
||||
// zmq_errno() — but we normalize to them for portability (see
|
||||
// normalize_to_zmq).
|
||||
// +51..54 — ZMQ-native codes (EFSM, ENOCOMPATPROTO, ETERM, EMTHREAD).
|
||||
// Always ZMQ-specific, defined unconditionally.
|
||||
//
|
||||
// The value is fixed by libzmq's ABI-stability promise (zmq.h): "the value
|
||||
// of constants must not change, and old values may not be reused". A C
|
||||
// #define is not a linkable symbol, so hardcoding is the only option.
|
||||
HAUSNUMERO :: 156384712
|
||||
|
||||
ZMQ_Error :: enum c.int {
|
||||
// Fallback POSIX errnos — ZMQ's own values for these errnos, used on
|
||||
// platforms where the C <errno.h> doesn't define them. We normalize
|
||||
// all platforms to these values via normalize_to_zmq so that the same
|
||||
// logical error always has the same value and lands in ZMQ_Error
|
||||
// regardless of platform.
|
||||
ENOTSUP = HAUSNUMERO + 1,
|
||||
EPROTONOSUPPORT = HAUSNUMERO + 2,
|
||||
ENOBUFS = HAUSNUMERO + 3,
|
||||
ENETDOWN = HAUSNUMERO + 4,
|
||||
EADDRINUSE = HAUSNUMERO + 5,
|
||||
EADDRNOTAVAIL = HAUSNUMERO + 6,
|
||||
ECONNREFUSED = HAUSNUMERO + 7,
|
||||
EINPROGRESS = HAUSNUMERO + 8,
|
||||
ENOTSOCK = HAUSNUMERO + 9,
|
||||
EMSGSIZE = HAUSNUMERO + 10,
|
||||
EAFNOSUPPORT = HAUSNUMERO + 11,
|
||||
ENETUNREACH = HAUSNUMERO + 12,
|
||||
ECONNABORTED = HAUSNUMERO + 13,
|
||||
ECONNRESET = HAUSNUMERO + 14,
|
||||
ENOTCONN = HAUSNUMERO + 15,
|
||||
ETIMEDOUT = HAUSNUMERO + 16,
|
||||
EHOSTUNREACH = HAUSNUMERO + 17,
|
||||
ENETRESET = HAUSNUMERO + 18,
|
||||
|
||||
// ZMQ-native error codes.
|
||||
EFSM = HAUSNUMERO + 51,
|
||||
ENOCOMPATPROTO = HAUSNUMERO + 52,
|
||||
ETERM = HAUSNUMERO + 53,
|
||||
EMTHREAD = HAUSNUMERO + 54,
|
||||
}
|
||||
|
||||
// Map platform-native POSIX errnos to ZMQ fallback values.
|
||||
//
|
||||
// The 18 errnos below have different numeric values on different platforms
|
||||
// (e.g. EADDRINUSE is 98 on Linux, 100 on Windows, 48 on macOS). By
|
||||
// translating them to ZMQ's canonical fallback values (HAUSNUMERO+offset),
|
||||
// the same logical error always lands in ZMQ_Error with the same value
|
||||
// on every platform — enabling portable pattern matching.
|
||||
//
|
||||
// Errnos not in this list (EAGAIN, EINTR, EACCES, ...) pass through
|
||||
// unchanged and are classified as Platform_Error.
|
||||
normalize_to_zmq :: proc(raw: c.int) -> c.int {
|
||||
#partial switch os.Platform_Error(raw) {
|
||||
// ENOTSUP shares its value with EOPNOTSUPP on Linux/macOS (both are
|
||||
// the same constant). On Windows they differ (129 vs 130), but MSVC-
|
||||
// compiled libzmq uses the ZMQ fallback (HAUSNUMERO+1) anyway, so
|
||||
// .EOPNOTSUPP here only needs to match the Linux/macOS value.
|
||||
case .EOPNOTSUPP:
|
||||
return HAUSNUMERO + 1
|
||||
case .EPROTONOSUPPORT:
|
||||
return HAUSNUMERO + 2
|
||||
case .ENOBUFS:
|
||||
return HAUSNUMERO + 3
|
||||
case .ENETDOWN:
|
||||
return HAUSNUMERO + 4
|
||||
case .EADDRINUSE:
|
||||
return HAUSNUMERO + 5
|
||||
case .EADDRNOTAVAIL:
|
||||
return HAUSNUMERO + 6
|
||||
case .ECONNREFUSED:
|
||||
return HAUSNUMERO + 7
|
||||
case .EINPROGRESS:
|
||||
return HAUSNUMERO + 8
|
||||
case .ENOTSOCK:
|
||||
return HAUSNUMERO + 9
|
||||
case .EMSGSIZE:
|
||||
return HAUSNUMERO + 10
|
||||
case .EAFNOSUPPORT:
|
||||
return HAUSNUMERO + 11
|
||||
case .ENETUNREACH:
|
||||
return HAUSNUMERO + 12
|
||||
case .ECONNABORTED:
|
||||
return HAUSNUMERO + 13
|
||||
case .ECONNRESET:
|
||||
return HAUSNUMERO + 14
|
||||
case .ENOTCONN:
|
||||
return HAUSNUMERO + 15
|
||||
case .ETIMEDOUT:
|
||||
return HAUSNUMERO + 16
|
||||
case .EHOSTUNREACH:
|
||||
return HAUSNUMERO + 17
|
||||
case .ENETRESET:
|
||||
return HAUSNUMERO + 18
|
||||
case:
|
||||
return raw
|
||||
}
|
||||
}
|
||||
|
||||
// Reverse of normalize_to_zmq: maps ZMQ fallback values back to
|
||||
// platform-native errno values.
|
||||
//
|
||||
// zmq_strerror only has string entries for ZMQ-native codes (HAUSNUMERO+51..54)
|
||||
// and delegates everything else to C's strerror, which only knows platform-native
|
||||
// errno values. The ZMQ fallback values (HAUSNUMERO+1..18) are in a gap — neither
|
||||
// ZMQ-native nor platform-native — so zmq_strerror returns "Unknown error" for them.
|
||||
// This function reverses the normalization so strerror produces the correct string.
|
||||
denormalize_from_zmq :: proc(zmq_val: c.int) -> c.int {
|
||||
#partial switch ZMQ_Error(zmq_val) {
|
||||
case .ENOTSUP:
|
||||
return c.int(os.Platform_Error.EOPNOTSUPP)
|
||||
case .EPROTONOSUPPORT:
|
||||
return c.int(os.Platform_Error.EPROTONOSUPPORT)
|
||||
case .ENOBUFS:
|
||||
return c.int(os.Platform_Error.ENOBUFS)
|
||||
case .ENETDOWN:
|
||||
return c.int(os.Platform_Error.ENETDOWN)
|
||||
case .EADDRINUSE:
|
||||
return c.int(os.Platform_Error.EADDRINUSE)
|
||||
case .EADDRNOTAVAIL:
|
||||
return c.int(os.Platform_Error.EADDRNOTAVAIL)
|
||||
case .ECONNREFUSED:
|
||||
return c.int(os.Platform_Error.ECONNREFUSED)
|
||||
case .EINPROGRESS:
|
||||
return c.int(os.Platform_Error.EINPROGRESS)
|
||||
case .ENOTSOCK:
|
||||
return c.int(os.Platform_Error.ENOTSOCK)
|
||||
case .EMSGSIZE:
|
||||
return c.int(os.Platform_Error.EMSGSIZE)
|
||||
case .EAFNOSUPPORT:
|
||||
return c.int(os.Platform_Error.EAFNOSUPPORT)
|
||||
case .ENETUNREACH:
|
||||
return c.int(os.Platform_Error.ENETUNREACH)
|
||||
case .ECONNABORTED:
|
||||
return c.int(os.Platform_Error.ECONNABORTED)
|
||||
case .ECONNRESET:
|
||||
return c.int(os.Platform_Error.ECONNRESET)
|
||||
case .ENOTCONN:
|
||||
return c.int(os.Platform_Error.ENOTCONN)
|
||||
case .ETIMEDOUT:
|
||||
return c.int(os.Platform_Error.ETIMEDOUT)
|
||||
case .EHOSTUNREACH:
|
||||
return c.int(os.Platform_Error.EHOSTUNREACH)
|
||||
case .ENETRESET:
|
||||
return c.int(os.Platform_Error.ENETRESET)
|
||||
case:
|
||||
return zmq_val
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
last_error :: proc() -> Error {
|
||||
raw := errno()
|
||||
normalized := normalize_to_zmq(raw)
|
||||
|
||||
#partial switch ZMQ_Error(normalized) {
|
||||
case .ENOTSUP,
|
||||
.EPROTONOSUPPORT,
|
||||
.ENOBUFS,
|
||||
.ENETDOWN,
|
||||
.EADDRINUSE,
|
||||
.EADDRNOTAVAIL,
|
||||
.ECONNREFUSED,
|
||||
.EINPROGRESS,
|
||||
.ENOTSOCK,
|
||||
.EMSGSIZE,
|
||||
.EAFNOSUPPORT,
|
||||
.ENETUNREACH,
|
||||
.ECONNABORTED,
|
||||
.ECONNRESET,
|
||||
.ENOTCONN,
|
||||
.ETIMEDOUT,
|
||||
.EHOSTUNREACH,
|
||||
.ENETRESET,
|
||||
.EFSM,
|
||||
.ENOCOMPATPROTO,
|
||||
.ETERM,
|
||||
.EMTHREAD:
|
||||
return ZMQ_Error(normalized)
|
||||
case:
|
||||
return os.Platform_Error(raw)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-19
@@ -59,35 +59,17 @@ Flags :: bit_set[Flag;c.int]
|
||||
|
||||
NoBlock :: Flags{.DONTWAIT}
|
||||
|
||||
HAUSNUMERO :: 156384712
|
||||
|
||||
ZMQ_Error :: enum c.int {
|
||||
EFSM = HAUSNUMERO + 51,
|
||||
ENOCOMPATPROTO = HAUSNUMERO + 52,
|
||||
ETERM = HAUSNUMERO + 53,
|
||||
EMTHREAD = HAUSNUMERO + 54,
|
||||
}
|
||||
|
||||
Error :: union #shared_nil {
|
||||
os.Platform_Error,
|
||||
ZMQ_Error,
|
||||
}
|
||||
|
||||
last_error :: proc() -> Error {
|
||||
raw := errno()
|
||||
|
||||
if raw >= HAUSNUMERO {
|
||||
return ZMQ_Error(raw)
|
||||
}
|
||||
return os.Platform_Error(raw)
|
||||
}
|
||||
|
||||
strerror :: proc(e: Error) -> cstring {
|
||||
switch v in e {
|
||||
case os.Platform_Error:
|
||||
return _strerror(c.int(v))
|
||||
case ZMQ_Error:
|
||||
return _strerror(c.int(v))
|
||||
return _strerror(denormalize_from_zmq(c.int(v)))
|
||||
case:
|
||||
return _strerror(0)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user