Nanomsg/NNG Wrapper for PureBasic Programming Language.
Note: nanomsg is no longer maintained. For new work, use the sibling package
PureBasicNNG(NNG / nanomsg-next-gen). The APIs are not compatible.
Building requires PureBasic Compiler and test under Windows 11.
Module features require PureBasic 5.20 and above.
Bundled runtime: PureBasicNanoMsg/Library/x64/nanomsg.dll (x64 only).
NnSetsockopt/NanomsgSocket::Setsockopttake a pointer (*optval).- Use
NnSetsockoptString/SetsockoptStringfor topic strings (NN_SUB_SUBSCRIBE). - Use
NnSetsockoptInt/SetsockoptIntfor integer options (NN_RCVTIMEO, …). NnGetsockoptrequires*optvallen(in/out length), matching the C API.NnSendtakes a buffer pointer; useNnSendString/SendStringfor text.NnPoll+NnPollFdsupport non-blocking readiness checks.- Zero-copy helpers:
NnAllocmsg/NnReallocmsg/NnFreemsgwith#NN_MSG. - Scatter/gather:
NnSendmsg/NnRecvmsgwithNnIovec/NnMsghdr(seeSendmsgIovecexample). - Ancillary helpers:
NnCmsgFirstHdr/NnCmsgNxtHdr/NnCmsgData/NnCmsgSpace/NnCmsgLen. NnDllOpenresolves allnn_*exports once intogNnFuncs(FuncTable.pbi); later calls reuse the cache.- Examples check DLL/socket/bind|connect return values and use
PeekS(buf, recvRc, #PB_Ascii)(nn_recv has no null terminator).
Publisher Server
EnableExplicit
IncludeFile "../../Core/Enums.pbi"
IncludeFile "../../Core/NanomsgWrapper.pbi"
UseModule NanomsgWrapper
Global lpszCurrentDir.s = GetCurrentDirectory()
; Nanomsg version (x64)
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
Global lpszLibNnDir.s = "Library/x64"
Global lpszLibNnDll.s = lpszCurrentDir + lpszLibNnDir + "/nanomsg.dll"
SetCurrentDirectory(lpszCurrentDir + lpszLibNnDir)
CompilerElse
CompilerError "Only x64 nanomsg.dll is bundled."
CompilerEndIf
Global lpszServerAddr.s = "tcp://*:1689"
If DllOpen(lpszLibNnDll) = 0
OpenConsole()
PrintN("Failed to open nanomsg.dll: " + lpszLibNnDll)
CloseConsole()
End 1
EndIf
OpenConsole()
Define Socket.i = NanomsgSocket::Socket(#AF_SP, #NN_PUB)
If Socket < 0
PrintN("Socket failed: " + NanomsgRuntime::Strerror(NanomsgRuntime::Errno()))
CloseConsole()
DllClose()
End 1
EndIf
Define Rc.i = NanomsgSocket::Bind(Socket, lpszServerAddr)
If Rc < 0
PrintN("Bind failed: " + NanomsgRuntime::Strerror(NanomsgRuntime::Errno()))
NanomsgSocket::Close(Socket)
CloseConsole()
DllClose()
End 1
EndIf
PrintN("Bind an IP address: " + lpszServerAddr)
While 1
Define lpszTopic.s = "quotes"
; Prefix must match NN_SUB_SUBSCRIBE filter on the subscriber.
Define lpszMessage.s = lpszTopic + "#Bid:" + Random(9000, 1000) + ",Ask:" + Random(9000, 1000)
Rc = NanomsgSocket::SendString(Socket, lpszMessage, Len(lpszMessage), 0)
If Rc >= 0
PrintN("Published: " + lpszMessage)
Else
PrintN("Send failed: " + NanomsgRuntime::Strerror(NanomsgRuntime::Errno()))
EndIf
Delay(500)
Wend
NanomsgSocket::Close(Socket)
CloseConsole()
DllClose()
Subscribe Client
EnableExplicit
IncludeFile "../../Core/Enums.pbi"
IncludeFile "../../Core/NanomsgWrapper.pbi"
UseModule NanomsgWrapper
Global lpszCurrentDir.s = GetCurrentDirectory()
; Nanomsg version (x64)
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
Global lpszLibNnDir.s = "Library/x64"
Global lpszLibNnDll.s = lpszCurrentDir + lpszLibNnDir + "/nanomsg.dll"
SetCurrentDirectory(lpszCurrentDir + lpszLibNnDir)
CompilerElse
CompilerError "Only x64 nanomsg.dll is bundled."
CompilerEndIf
Global lpszServerAddr.s = "tcp://localhost:1689"
If DllOpen(lpszLibNnDll) = 0
OpenConsole()
PrintN("Failed to open nanomsg.dll: " + lpszLibNnDll)
CloseConsole()
End 1
EndIf
OpenConsole()
Define Socket.i = NanomsgSocket::Socket(#AF_SP, #NN_SUB)
If Socket < 0
PrintN("Socket failed: " + NanomsgRuntime::Strerror(NanomsgRuntime::Errno()))
CloseConsole()
DllClose()
End 1
EndIf
Define Rc.i = NanomsgSocket::Connect(Socket, lpszServerAddr)
If Rc < 0
PrintN("Connect failed: " + NanomsgRuntime::Strerror(NanomsgRuntime::Errno()))
NanomsgSocket::Close(Socket)
CloseConsole()
DllClose()
End 1
EndIf
Define lpszSubscribe.s = "quotes"
Rc = NanomsgSocket::SetsockoptString(Socket, #NN_SUB, #NN_SUB_SUBSCRIBE, lpszSubscribe)
If Rc < 0
PrintN("Subscribe failed: " + NanomsgRuntime::Strerror(NanomsgRuntime::Errno()))
NanomsgSocket::Close(Socket)
CloseConsole()
DllClose()
End 1
EndIf
While 1
Define *lpszBuffer = AllocateMemory(256)
Define recvRc.i = NanomsgSocket::Recv(Socket, *lpszBuffer, MemorySize(*lpszBuffer), 0)
; nn_recv does not append a null terminator; use the returned length.
If recvRc >= 0
PrintN(PeekS(*lpszBuffer, recvRc, #PB_Ascii))
Else
PrintN("Recv failed: " + NanomsgRuntime::Strerror(NanomsgRuntime::Errno()))
EndIf
FreeMemory(*lpszBuffer)
Wend
NanomsgSocket::Close(Socket)
Input()
CloseConsole()
DllClose()
More samples under PureBasicNanoMsg/Example:
- PUB/SUB, REQ/REP, PUSH/PULL (with
NnPoll) - Survey (
SurveyorServer/RespondentClient, deadline +ETIMEDOUT/EFSM) - Bus (
BusServer/BusClient, bidirectional withNnPoll) - PAIR +
inproc://smoke test (PairInproc) nn_sendmsg/nn_recvmsgiovec smoke test (SendmsgIovec)
Copyright (c) 2017-2026 Ji-Feng Tsai.
Code released under the MIT license.
nn_device
If this application help you reduce time to coding, you can give me a cup of coffee :)
