Class: ZMQ::Message
Overview
The factory constructor optionally takes a string as an argument. It will copy this string to native memory in preparation for transmission. So, don’t pass a string unless you intend to send it. Internally it calls #copy_in_string.
Call #close to release buffers when you are done with the data.
(This class is not really zero-copy. Ruby makes this near impossible since Ruby objects can be relocated in memory by the GC at any time. There is no way to peg them to native memory or have them use non-movable native memory as backing store.)
Message represents ruby equivalent of the zmq_msg_t
C struct. Access the underlying memory buffer and the buffer size using the #data and #size methods respectively.
It is recommended that this class be composed inside another class for access to the underlying buffer. The outer wrapper class can provide nice accessors for the information in the data buffer; a clever implementation can probably lazily encode/decode the data buffer on demand. Lots of protocols send more information than is strictly necessary, so only decode (copy from the 0mq buffer to Ruby) that which is necessary.
When you are done using a received message object, call #close to release the associated buffers.
received_message = Message.create
if received_message
rc = socket.recv(received_message)
if ZMQ::Util.resultcode_ok?(rc)
puts "Message contained: #{received_message.copy_out_string}"
else
STDERR.puts "Error when receiving message: #{ZMQ::Util.error_string}"
end
Define a custom layout for the data sent between 0mq peers.
class MyMessage
class Layout < FFI::Struct
layout :value1, :uint8,
:value2, :uint64,
:value3, :uint32,
:value4, [:char, 30]
end
def initialize msg_struct = nil
if msg_struct
@msg_t = msg_struct
@data = Layout.new(@msg_t.data)
else
@pointer = FFI::MemoryPointer.new :byte, Layout.size, true
@data = Layout.new @pointer
end
end
def size() @size = @msg_t.size; end
def value1
@data[:value1]
end
def value4
@data[:value4].to_ptr.read_string
end
def value1=(val)
@data[:value1] = val
end
def create_sendable_message
msg = Message.new
msg.copy_in_bytes @pointer, Layout.size
end
message = Message.new
successful_read = socket.recv message
message = MyMessage.new message if successful_read
puts "value1 is #{message.value1}"
Direct Known Subclasses
Class Method Summary collapse
-
.create(message = nil) ⇒ Object
Recommended way to create a standard message.
Instance Method Summary collapse
-
#address ⇒ Object
(also: #pointer)
Provides the memory address of the
zmq_msg_t
struct. -
#close ⇒ Object
Manually release the message struct and its associated data buffer.
- #copy(source) ⇒ Object
-
#copy_in_bytes(bytes, len) ⇒ Object
Makes a copy of
len
bytes from the ruby stringbytes
. -
#copy_in_string(string) ⇒ Object
Makes a copy of the ruby
string
into a native memory buffer so that libzmq can send it. -
#copy_out_string ⇒ Object
Returns the data buffer as a string.
-
#data ⇒ Object
Returns a pointer to the data buffer.
-
#initialize(message = nil) ⇒ Message
constructor
A new instance of Message.
- #move(source) ⇒ Object
-
#size ⇒ Object
Provides the size of the data buffer for this
zmq_msg_t
C struct.
Methods included from Util
errno, error_string, nonblocking_flag, resultcode_ok?, version
Constructor Details
#initialize(message = nil) ⇒ Message
Returns a new instance of Message.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/ffi-rzmq/message.rb', line 96 def initialize = nil @state = :uninitialized # allocate our own pointer so that we can tell it to *not* zero out # the memory; it's pointless work since the library is going to # overwrite it anyway. @pointer = FFI::MemoryPointer.new LibZMQ::Msg.size, 1, false if copy_in_string else # initialize an empty message structure to receive a message result_code = LibZMQ.zmq_msg_init @pointer raise unless Util.resultcode_ok?(result_code) end end |
Class Method Details
.create(message = nil) ⇒ Object
Recommended way to create a standard message. A Message object is returned upon success, nil when allocation fails.
92 93 94 |
# File 'lib/ffi-rzmq/message.rb', line 92 def self.create = nil new() rescue nil end |
Instance Method Details
#address ⇒ Object Also known as: pointer
Provides the memory address of the zmq_msg_t
struct. Used mostly for passing to other methods accessing the underlying library that require a real data address.
144 145 146 |
# File 'lib/ffi-rzmq/message.rb', line 144 def address @pointer end |
#close ⇒ Object
Manually release the message struct and its associated data buffer.
Only releases the buffer a single time. Subsequent calls are no ops.
186 187 188 189 190 191 192 193 194 195 |
# File 'lib/ffi-rzmq/message.rb', line 186 def close rc = 0 if @pointer rc = LibZMQ.zmq_msg_close @pointer @pointer = nil end rc end |
#copy(source) ⇒ Object
149 150 151 |
# File 'lib/ffi-rzmq/message.rb', line 149 def copy source LibZMQ.zmq_msg_copy @pointer, source.address end |
#copy_in_bytes(bytes, len) ⇒ Object
Makes a copy of len
bytes from the ruby string bytes
. Library handles deallocation of the native memory buffer.
Can only be initialized via #copy_in_string or #copy_in_bytes once.
129 130 131 132 133 134 135 136 137 138 |
# File 'lib/ffi-rzmq/message.rb', line 129 def copy_in_bytes bytes, len data_buffer = LibC.malloc len # writes the exact number of bytes, no null byte to terminate string data_buffer.write_string bytes, len # use libC to call free on the data buffer; earlier versions used an # FFI::Function here that called back into Ruby, but Rubinius won't # support that and there are issues with the other runtimes too LibZMQ.zmq_msg_init_data @pointer, data_buffer, len, LibC::Free, nil end |
#copy_in_string(string) ⇒ Object
Makes a copy of the ruby string
into a native memory buffer so that libzmq can send it. The underlying library will handle deallocation of the native memory buffer.
Can only be initialized via #copy_in_string or #copy_in_bytes once.
119 120 121 122 |
# File 'lib/ffi-rzmq/message.rb', line 119 def copy_in_string string string_size = string.respond_to?(:bytesize) ? string.bytesize : string.size copy_in_bytes string, string_size if string end |
#copy_out_string ⇒ Object
Returns the data buffer as a string.
Note: If this is binary data, it won’t print very prettily.
176 177 178 |
# File 'lib/ffi-rzmq/message.rb', line 176 def copy_out_string data.read_string(size) end |
#data ⇒ Object
Returns a pointer to the data buffer. This pointer should never be freed. It will automatically be freed when the message
object goes out of scope and gets garbage collected.
168 169 170 |
# File 'lib/ffi-rzmq/message.rb', line 168 def data LibZMQ.zmq_msg_data @pointer end |
#move(source) ⇒ Object
153 154 155 |
# File 'lib/ffi-rzmq/message.rb', line 153 def move source LibZMQ.zmq_msg_move @pointer, source.address end |
#size ⇒ Object
Provides the size of the data buffer for this zmq_msg_t
C struct.
159 160 161 |
# File 'lib/ffi-rzmq/message.rb', line 159 def size LibZMQ.zmq_msg_size @pointer end |