1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
require 'open3'
require 'rbconfig'
# Wraps the libzmq library and attaches to the functions that are
# common across the 3.2.x+ and 4.x APIs.
#
module LibZMQ
extend FFI::Library
begin
ZMQ_LIB_PATHS = []
# Recent versions of libzmq do not put all symbols into the global namespace so
# lazy linking can fail at runtime. Force all symbols to global namespace.
ffi_lib_flags :now, :global
ffi_lib 'libzmq.so.5'
rescue LoadError
# Failed to load the zmq library
found_libs = ZMQ_LIB_PATHS.find_all {|path| File.file? path }
if found_libs.any?
warn "Unable to load this gem. The libzmq library exists, but cannot be loaded."
warn "libzmq library was found at:"
warn found_libs.inspect
if FFI::Platform::IS_WINDOWS
warn "On Windows:"
warn "- Check that you have MSVC runtime installed or statically linked"
warn "- Check that your DLL is compiled for #{FFI::Platform::ADDRESS_SIZE} bit"
end
else
warn "Unable to load this gem. The libzmq library (or DLL) could not be found."
warn "If this is a Windows platform, make sure libzmq.dll is on the PATH."
warn "If the DLL was built with mingw, make sure the other two dependent DLLs,"
warn "libgcc_s_sjlj-1.dll and libstdc++6.dll, are also on the PATH."
warn "For non-Windows platforms, make sure libzmq is located in this search path:"
warn ZMQ_LIB_PATHS.inspect
end
raise LoadError, "The libzmq library (or DLL) could not be loaded"
end
# Size_t not working properly on Windows
find_type(:size_t) rescue typedef(:ulong, :size_t)
# Context and misc api
#
# The `:blocking` option is a hint to FFI that the following (and only the following)
# function may block, therefore it should release the GIL before calling it.
# This can aid in situations where the function call will/may block and another
# thread within the lib may try to call back into the ruby runtime. Failure to
# release the GIL will result in a hang; the hint is required for MRI otherwise
# there are random hangs (which require kill -9 to terminate).
#
attach_function :zmq_version, [:pointer, :pointer, :pointer], :void, :blocking => true
attach_function :zmq_errno, [], :int, :blocking => true
attach_function :zmq_strerror, [:int], :pointer, :blocking => true
# Context initialization and destruction
attach_function :zmq_init, [:int], :pointer, :blocking => true
attach_function :zmq_term, [:pointer], :int, :blocking => true
attach_function :zmq_ctx_new, [], :pointer, :blocking => true
attach_function :zmq_ctx_destroy, [:pointer], :int, :blocking => true
attach_function :zmq_ctx_set, [:pointer, :int, :int], :int, :blocking => true
attach_function :zmq_ctx_get, [:pointer, :int], :int, :blocking => true
# Message API
attach_function :zmq_msg_init, [:pointer], :int, :blocking => true
attach_function :zmq_msg_init_size, [:pointer, :size_t], :int, :blocking => true
attach_function :zmq_msg_init_data, [:pointer, :pointer, :size_t, :pointer, :pointer], :int, :blocking => true
attach_function :zmq_msg_close, [:pointer], :int, :blocking => true
attach_function :zmq_msg_data, [:pointer], :pointer, :blocking => true
attach_function :zmq_msg_size, [:pointer], :size_t, :blocking => true
attach_function :zmq_msg_copy, [:pointer, :pointer], :int, :blocking => true
attach_function :zmq_msg_move, [:pointer, :pointer], :int, :blocking => true
attach_function :zmq_msg_send, [:pointer, :pointer, :int], :int, :blocking => true
attach_function :zmq_msg_recv, [:pointer, :pointer, :int], :int, :blocking => true
attach_function :zmq_msg_more, [:pointer], :int, :blocking => true
attach_function :zmq_msg_get, [:pointer, :int], :int, :blocking => true
attach_function :zmq_msg_set, [:pointer, :int, :int], :int, :blocking => true
# Socket API
attach_function :zmq_socket, [:pointer, :int], :pointer, :blocking => true
attach_function :zmq_setsockopt, [:pointer, :int, :pointer, :int], :int, :blocking => true
attach_function :zmq_getsockopt, [:pointer, :int, :pointer, :pointer], :int, :blocking => true
attach_function :zmq_bind, [:pointer, :string], :int, :blocking => true
attach_function :zmq_connect, [:pointer, :string], :int, :blocking => true
attach_function :zmq_close, [:pointer], :int, :blocking => true
attach_function :zmq_unbind, [:pointer, :string], :int, :blocking => true
attach_function :zmq_disconnect, [:pointer, :string], :int, :blocking => true
attach_function :zmq_recvmsg, [:pointer, :pointer, :int], :int, :blocking => true
attach_function :zmq_recv, [:pointer, :pointer, :size_t, :int], :int, :blocking => true
attach_function :zmq_sendmsg, [:pointer, :pointer, :int], :int, :blocking => true
attach_function :zmq_send, [:pointer, :pointer, :size_t, :int], :int, :blocking => true
# Device API
attach_function :zmq_proxy, [:pointer, :pointer, :pointer], :int, :blocking => true
# Poll API
attach_function :zmq_poll, [:pointer, :int, :long], :int, :blocking => true
# Monitoring API
attach_function :zmq_socket_monitor, [:pointer, :pointer, :int], :int, :blocking => true
# Wrapper function for context termination
def self.terminate_context(context)
zmq_ctx_destroy(context)
end
end
|