Skip to content

Latest commit

 

History

74 Commits

Folders and files

Repository files navigation

PureBasicZMQ

ZMQ Wrapper for PureBasic Programming Language.

GitHub PureBasic Dependency

Environment

  • Windows 10 above (recommend)
  • PureBasic 6.0 above (recommend)
  • ZeroMQ (libzmq 4.3.6 API constants; runtime version comes from your DLL)

How to Build

Building requires PureBasic Compiler and test under Windows 11.
Module features require PureBasic 5.20 and above.

Place libzmq.dll under PureBasicZMQ/Library/x64 or PureBasicZMQ/Library/x86 (examples resolve the path from the processor).

Return Values and Errors

libzmq conventions apply:

  • Most calls return 0 on success and -1 on failure (for example Bind, Connect, Setsockopt, Close).
  • Send / Recv return the number of bytes on success, or -1 on failure.
  • Socket / CtxNew return a non-zero handle on success, or 0/null on failure.
  • After a failed call, use ZmqErrno() / ZmqRuntime::Errno() and ZmqStrerror() / ZmqRuntime::Strerror() for the reason.
  • Do not treat every 0 as failure: 0 is success for many APIs.

Example:

Define Rc.i = ZmqSocket::Bind(Socket, lpszServerAddr)

If Rc <> 0
  PrintN("Bind failed: " + ZmqRuntime::Strerror(ZmqRuntime::Errno()))
EndIf

Example

Publisher Server (ZMQ_PUB is send-only — do not call Recv on it)

EnableExplicit

IncludeFile "../../Core/Enums.pbi"
IncludeFile "../../Core/ZeroMQWrapper.pbi"

UseModule ZeroMQWrapper

Global lpszLibZmqDll.s = "libzmq.dll"
Global lpszServerAddr.s = "tcp://*:1689"

If DllOpen(lpszLibZmqDll)
  OpenConsole()
  
  Define Context.i = ZmqContext::New()
  Define Socket.i = ZmqSocket::Socket(Context, #ZMQ_PUB)
  Define Rc.i = ZmqSocket::Bind(Socket, lpszServerAddr)
  
  If Rc <> 0
    PrintN("Bind failed: " + ZmqRuntime::Strerror(ZmqRuntime::Errno()))
  Else
    PrintN("Bind an IP address: " + lpszServerAddr)
    Delay(200) ; slow joiner: give subscribers time to connect
    
    While 1
      Define lpszTopic.s = "quotes"
      Define lpszMessage.s = "Bid:" + Random(9000, 1000) + ",Ask:" + Random(9000, 1000)
      
      If ZmqSocket::Send(Socket, lpszTopic, Len(lpszTopic), #ZMQ_SNDMORE) = -1
        PrintN("Send topic failed: " + ZmqRuntime::Strerror(ZmqRuntime::Errno()))
      ElseIf ZmqSocket::Send(Socket, lpszMessage, Len(lpszMessage), 0) = -1
        PrintN("Send message failed: " + ZmqRuntime::Strerror(ZmqRuntime::Errno()))
      Else
        PrintN("Published: " + lpszMessage)
      EndIf
      
      Delay(100)
    Wend
  EndIf
  
  ZmqSocket::Close(Socket)
  ZmqContext::Shutdown(Context)
  
  CloseConsole()
  
  DllClose()
EndIf

Subscribe Client

EnableExplicit

IncludeFile "../../Core/Enums.pbi"
IncludeFile "../../Core/ZeroMQWrapper.pbi"

UseModule ZeroMQWrapper

Global lpszLibZmqDll.s = "libzmq.dll"
Global lpszServerAddr.s = "tcp://localhost:1689"

If DllOpen(lpszLibZmqDll)
  OpenConsole()
  
  Define Context.i = ZmqContext::New()
  Define Socket.i = ZmqSocket::Socket(Context, #ZMQ_SUB)
  Define lpszSubscribe.s = "quotes"
  
  ; Subscribe before connect to reduce missed early messages.
  ZmqSocket::Setsockopt(Socket, #ZMQ_SUBSCRIBE, lpszSubscribe, Len(lpszSubscribe))
  
  Define Rc.i = ZmqSocket::Connect(Socket, lpszServerAddr)
  
  If Rc <> 0
    PrintN("Connect failed: " + ZmqRuntime::Strerror(ZmqRuntime::Errno()))
  Else
    While 1
      Define *lpszTopicBuffer = AllocateMemory(256)
      Define *lpszBuffer = AllocateMemory(256)
      Define TopicBytes.i
      Define MessageBytes.i
      
      TopicBytes = ZmqSocket::Recv(Socket, *lpszTopicBuffer, MemorySize(*lpszTopicBuffer), 0)
      
      If TopicBytes = -1
        PrintN("Recv topic failed: " + ZmqRuntime::Strerror(ZmqRuntime::Errno()))
      Else
        MessageBytes = ZmqSocket::Recv(Socket, *lpszBuffer, MemorySize(*lpszBuffer), 0)
        
        If MessageBytes = -1
          PrintN("Recv message failed: " + ZmqRuntime::Strerror(ZmqRuntime::Errno()))
        Else
          ; Use Recv byte count — ZMQ payloads are not null-terminated.
          PrintN(PeekS(*lpszBuffer, MessageBytes, #PB_UTF8))
        EndIf
      EndIf
      
      FreeMemory(*lpszTopicBuffer)
      FreeMemory(*lpszBuffer)
    Wend
  EndIf
  
  ZmqSocket::Close(Socket)
  ZmqContext::Shutdown(Context)
  
  CloseConsole()
  
  DllClose()
EndIf

Examples

Pattern Low-level Module Port
PUB / SUB PubServer.pb, SubClient.pb Module/PubServer.pb, Module/SubClient.pb 1689
REQ / REP ReqClient.pb, RepServer.pb Module/ReqClient.pb, Module/RepServer.pb 1700
PUSH / PULL PushServer.pb, PullClient.pb Module/PushServer.pb, Module/PullClient.pb 1701
DEALER / ROUTER DealerClient.pb, RouterServer.pb Module/DealerClient.pb, Module/RouterServer.pb 1702
PAIR PairClient.pb, PairServer.pb Module/PairClient.pb, Module/PairServer.pb 1703
STREAM StreamClient.pb, StreamServer.pb Module/StreamClient.pb, Module/StreamServer.pb 1704
Multipart helpers Frames.pb Module/Frames.pb 1705
Monitor Monitor.pb Module/Monitor.pb 1700 (+ inproc)

Also: Has, Poll, Proxy, Z85, Curve*, Plain, Msg, Thread, Stopwatch, Weather.

Multipart API (Core/Frames.pbi / ZmqFrames): SendFrames, SendStrings, RecvAllFrames, FramesFree, HasRcvMore, FrameToStr.

License

Copyright (c) 2017-2026 Ji-Feng Tsai.
Code released under the MIT license.

Donation

If this application help you reduce time to coding, you can give me a cup of coffee :)

paypal

Paypal Me

Releases

Packages

Contributors

Languages