ffi-rzmq-core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.travis.yml +15 -0
- data/LICENSE +20 -0
- data/README.md +13 -0
- data/ffi-rzmq-core.gemspec +25 -0
- data/lib/ffi-rzmq-core.rb +6 -0
- data/lib/ffi-rzmq-core/constants.rb +213 -0
- data/lib/ffi-rzmq-core/libc.rb +19 -0
- data/lib/ffi-rzmq-core/libzmq.rb +100 -0
- data/lib/ffi-rzmq-core/structures.rb +96 -0
- data/lib/ffi-rzmq-core/utilities.rb +40 -0
- data/lib/ffi-rzmq-core/version.rb +3 -0
- data/spec/spec_helper.rb +8 -0
- metadata +102 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d251cf90787964d1767307c511f830c983dd47c0
|
4
|
+
data.tar.gz: dbc73d731823c0f445d56b3a06250e4bdea8d2cc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4a0b12abbb518be94ce38b80a65c3c494f76d7e527cbcb4e93ad801e066ef2d6553c5a0ed44c73aed998626d497e5d9e96f01fd0399407f5186bc100604f58d9
|
7
|
+
data.tar.gz: da40bae1ff70d829ec8b4f8bea9628417e3210138e83aa89f6e4d58fe5209103af8126ab48a2718f9b01416dc0fdcc268718e0c9e323bfd8a6213edc752739b9
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
before_install: sudo apt-get install libzmq3-dev
|
2
|
+
script: bundle exec rspec
|
3
|
+
language: ruby
|
4
|
+
rvm:
|
5
|
+
- 1.9.3
|
6
|
+
- 2.0.0
|
7
|
+
- ruby-head
|
8
|
+
- jruby-19mode
|
9
|
+
- jruby-head
|
10
|
+
- rbx-2.1.1
|
11
|
+
|
12
|
+
matrix:
|
13
|
+
allow_failures:
|
14
|
+
- rvm: ruby-head
|
15
|
+
- rvm: jruby-head
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Chuck Remes
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
ffi-rzmq-core
|
2
|
+
=============
|
3
|
+
|
4
|
+
The intention of this gem is to provide a very basic FFI wrapper around the Zeromq libzmq C API.
|
5
|
+
This gem isn't intended to be used directly by any Ruby programmer looking to write Zeromq code.
|
6
|
+
They should use a higher-level gem like ffi-rzmq which pulls in this gem for its FFI definitions.
|
7
|
+
|
8
|
+
There have been complaints that the ffi-rzmq gem doesn't provide the correct or best Ruby idioms, so I am
|
9
|
+
hoping this encourages other library writers to create their own. Rather than duplicate the FFI
|
10
|
+
wrapping code, they can just pull in this gem and build a more idiomatic library around the
|
11
|
+
basic definitions.
|
12
|
+
|
13
|
+
See [ffi-rzmq]
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "ffi-rzmq-core/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "ffi-rzmq-core"
|
7
|
+
s.version = LibZMQ::VERSION
|
8
|
+
s.authors = ["Chuck Remes"]
|
9
|
+
s.email = ["git@chuckremes.com"]
|
10
|
+
s.homepage = "http://github.com/chuckremes/ffi-rzmq-core"
|
11
|
+
s.summary = %q{This gem provides only the FFI wrapper for the ZeroMQ (0mq) networking library.}
|
12
|
+
s.description = %q{This gem provides only the FFI wrapper for the ZeroMQ (0mq) networking library.
|
13
|
+
Project can be used by any other zeromq gems that want to provide their own high-level Ruby API.}
|
14
|
+
|
15
|
+
s.license = 'MIT'
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_runtime_dependency "ffi", ["~> 1.9"]
|
23
|
+
s.add_development_dependency "rspec", ["~> 2.14"]
|
24
|
+
s.add_development_dependency "rake"
|
25
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
|
2
|
+
module ZMQ
|
3
|
+
# Set up all of the constants that are *common* to all API
|
4
|
+
# versions
|
5
|
+
|
6
|
+
# Socket types
|
7
|
+
PAIR = 0
|
8
|
+
PUB = 1
|
9
|
+
SUB = 2
|
10
|
+
REQ = 3
|
11
|
+
REP = 4
|
12
|
+
XREQ = 5
|
13
|
+
XREP = 6
|
14
|
+
PULL = 7
|
15
|
+
PUSH = 8
|
16
|
+
XPUB = 9
|
17
|
+
XSUB = 10
|
18
|
+
DEALER = XREQ
|
19
|
+
ROUTER = XREP
|
20
|
+
STREAM = 11
|
21
|
+
|
22
|
+
SocketTypeNameMap = {
|
23
|
+
PAIR => "PAIR",
|
24
|
+
PUB => "PUB",
|
25
|
+
SUB => "SUB",
|
26
|
+
REQ => "REQ",
|
27
|
+
REP => "REP",
|
28
|
+
PULL => "PULL",
|
29
|
+
PUSH => "PUSH",
|
30
|
+
XREQ => "XREQ",
|
31
|
+
XREP => "XREP",
|
32
|
+
ROUTER => "ROUTER",
|
33
|
+
DEALER => "DEALER",
|
34
|
+
XPUB => "XPUB",
|
35
|
+
XSUB => "XSUB",
|
36
|
+
STREAM => "STREAM",
|
37
|
+
}
|
38
|
+
|
39
|
+
# Socket options
|
40
|
+
AFFINITY = 4
|
41
|
+
IDENTITY = 5
|
42
|
+
SUBSCRIBE = 6
|
43
|
+
UNSUBSCRIBE = 7
|
44
|
+
RATE = 8
|
45
|
+
RECOVERY_IVL = 9
|
46
|
+
SNDBUF = 11
|
47
|
+
RCVBUF = 12
|
48
|
+
RCVMORE = 13
|
49
|
+
FD = 14
|
50
|
+
EVENTS = 15
|
51
|
+
TYPE = 16
|
52
|
+
LINGER = 17
|
53
|
+
RECONNECT_IVL = 18
|
54
|
+
BACKLOG = 19
|
55
|
+
RECONNECT_IVL_MAX = 21
|
56
|
+
MAXMSGSIZE = 22
|
57
|
+
SNDHWM = 23
|
58
|
+
RCVHWM = 24
|
59
|
+
MULTICAST_HOPS = 25
|
60
|
+
RCVTIMEO = 27
|
61
|
+
SNDTIMEO = 28
|
62
|
+
IPV4ONLY = 31
|
63
|
+
LAST_ENDPOINT = 32
|
64
|
+
ROUTER_MANDATORY = 33
|
65
|
+
TCP_KEEPALIVE = 34
|
66
|
+
TCP_KEEPALIVE_CNT = 35
|
67
|
+
TCP_KEEPALIVE_IDLE = 36
|
68
|
+
TCP_KEEPALIVE_INTVL = 37
|
69
|
+
TCP_ACCEPT_FILTER = 38
|
70
|
+
DELAY_ATTACH_ON_CONNECT = 39
|
71
|
+
XPUB_VERBOSE = 40
|
72
|
+
ROUTER_RAW = 41
|
73
|
+
IPV6 = 42
|
74
|
+
MECHANISM = 43
|
75
|
+
PLAIN_SERVER = 44
|
76
|
+
PLAIN_USERNAME = 45
|
77
|
+
PLAIN_PASSWORD = 46
|
78
|
+
CURVE_SERVER = 47
|
79
|
+
CURVE_PUBLICKEY = 48
|
80
|
+
CURVE_SECRETKEY = 49
|
81
|
+
CURVE_SERVERKEY = 50
|
82
|
+
PROBE_ROUTER = 51
|
83
|
+
REQ_CORRELATE = 52
|
84
|
+
REQ_RELAXED = 53
|
85
|
+
CONFLATE = 54
|
86
|
+
ZAP_DOMAIN = 55
|
87
|
+
ROUTER_HANDOVER = 56
|
88
|
+
|
89
|
+
IMMEDIATE = DELAY_ATTACH_ON_CONNECT
|
90
|
+
FAIL_UNROUTABLE = ROUTER_MANDATORY
|
91
|
+
ROUTER_BEHAVIOR = ROUTER_MANDATORY
|
92
|
+
|
93
|
+
# Socket Security Types
|
94
|
+
NULL = 0
|
95
|
+
PLAIN = 1
|
96
|
+
CURVE = 2
|
97
|
+
|
98
|
+
# Send/recv options
|
99
|
+
DONTWAIT = 1
|
100
|
+
SNDMORE = 2
|
101
|
+
SNDLABEL = 4
|
102
|
+
NOBLOCK = DONTWAIT
|
103
|
+
|
104
|
+
# Message options
|
105
|
+
MORE = 1
|
106
|
+
|
107
|
+
# Context options
|
108
|
+
IO_THREADS = 1
|
109
|
+
MAX_SOCKETS = 2
|
110
|
+
IO_THREADS_DFLT = 1
|
111
|
+
MAX_SOCKETS_DFLT = 1024
|
112
|
+
|
113
|
+
# I/O multiplexing
|
114
|
+
POLL = 1
|
115
|
+
POLLIN = 1
|
116
|
+
POLLOUT = 2
|
117
|
+
POLLERR = 4
|
118
|
+
|
119
|
+
# Socket errors
|
120
|
+
EAGAIN = Errno::EAGAIN::Errno
|
121
|
+
EINVAL = Errno::EINVAL::Errno
|
122
|
+
ENOMEM = Errno::ENOMEM::Errno
|
123
|
+
ENODEV = Errno::ENODEV::Errno
|
124
|
+
EFAULT = Errno::EFAULT::Errno
|
125
|
+
EINTR = Errno::EINTR::Errno
|
126
|
+
EMFILE = Errno::EMFILE::Errno
|
127
|
+
|
128
|
+
# ZMQ errors
|
129
|
+
HAUSNUMERO = 156384712
|
130
|
+
EFSM = (HAUSNUMERO + 51)
|
131
|
+
ENOCOMPATPROTO = (HAUSNUMERO + 52)
|
132
|
+
ETERM = (HAUSNUMERO + 53)
|
133
|
+
EMTHREAD = (HAUSNUMERO + 54)
|
134
|
+
|
135
|
+
# Rescue unknown constants and use the ZeroMQ defined values
|
136
|
+
# Usually only happens on Windows though some don't resolve on
|
137
|
+
# OSX too (ENOTSUP)
|
138
|
+
ENOTSUP = Errno::ENOTSUP::Errno rescue (HAUSNUMERO + 1)
|
139
|
+
EPROTONOSUPPORT = Errno::EPROTONOSUPPORT::Errno rescue (HAUSNUMERO + 2)
|
140
|
+
ENOBUFS = Errno::ENOBUFS::Errno rescue (HAUSNUMERO + 3)
|
141
|
+
ENETDOWN = Errno::ENETDOWN::Errno rescue (HAUSNUMERO + 4)
|
142
|
+
EADDRINUSE = Errno::EADDRINUSE::Errno rescue (HAUSNUMERO + 5)
|
143
|
+
EADDRNOTAVAIL = Errno::EADDRNOTAVAIL::Errno rescue (HAUSNUMERO + 6)
|
144
|
+
ECONNREFUSED = Errno::ECONNREFUSED::Errno rescue (HAUSNUMERO + 7)
|
145
|
+
EINPROGRESS = Errno::EINPROGRESS::Errno rescue (HAUSNUMERO + 8)
|
146
|
+
ENOTSOCK = Errno::ENOTSOCK::Errno rescue (HAUSNUMERO + 9)
|
147
|
+
EMSGSIZE = Errno::EMSGSIZE::Errno rescue (HAUSNUMERO + 10)
|
148
|
+
EAFNOSUPPORT = Errno::EAFNOSUPPORT::Errno rescue (HAUSNUMERO + 11)
|
149
|
+
ENETUNREACH = Errno::ENETUNREACH::Errno rescue (HAUSNUMERO + 12)
|
150
|
+
ECONNABORTED = Errno::ECONNABORTED::Errno rescue (HAUSNUMERO + 13)
|
151
|
+
ECONNRESET = Errno::ECONNRESET::Errno rescue (HAUSNUMERO + 14)
|
152
|
+
ENOTCONN = Errno::ENOTCONN::Errno rescue (HAUSNUMERO + 15)
|
153
|
+
ETIMEDOUT = Errno::ETIMEDOUT::Errno rescue (HAUSNUMERO + 16)
|
154
|
+
EHOSTUNREACH = Errno::EHOSTUNREACH::Errno rescue (HAUSNUMERO + 17)
|
155
|
+
ENETRESET = Errno::ENETRESET::Errno rescue (HAUSNUMERO + 18)
|
156
|
+
|
157
|
+
# Device Types
|
158
|
+
STREAMER = 1
|
159
|
+
FORWARDER = 2
|
160
|
+
QUEUE = 3
|
161
|
+
|
162
|
+
# Socket events and monitoring
|
163
|
+
EVENT_CONNECTED = 1
|
164
|
+
EVENT_CONNECT_DELAYED = 2
|
165
|
+
EVENT_CONNECT_RETRIED = 4
|
166
|
+
EVENT_LISTENING = 8
|
167
|
+
EVENT_BIND_FAILED = 16
|
168
|
+
EVENT_ACCEPTED = 32
|
169
|
+
EVENT_ACCEPT_FAILED = 64
|
170
|
+
EVENT_CLOSED = 128
|
171
|
+
EVENT_CLOSE_FAILED = 256
|
172
|
+
EVENT_DISCONNECTED = 512
|
173
|
+
EVENT_MONITOR_STOPPED = 1024
|
174
|
+
EVENT_ALL = (EVENT_CONNECTED | EVENT_CONNECT_DELAYED | EVENT_CONNECT_RETRIED |
|
175
|
+
EVENT_LISTENING | EVENT_BIND_FAILED | EVENT_ACCEPTED |
|
176
|
+
EVENT_ACCEPT_FAILED | EVENT_CLOSED | EVENT_CLOSE_FAILED |
|
177
|
+
EVENT_DISCONNECTED | EVENT_MONITOR_STOPPED)
|
178
|
+
|
179
|
+
# version checking
|
180
|
+
# This gem supports both libzmq 3.2+ and 4.x. However, not all socket options are visible between versions.
|
181
|
+
# To make support easier for consumers of this gem, we do all version checking here and only
|
182
|
+
# expose the appropriate socket options. Note that *all* options are defined above even if the library
|
183
|
+
# version doesn't support it. Consumers of this gem can enable support at runtime.
|
184
|
+
integer_socket_options = [
|
185
|
+
EVENTS, LINGER, RCVTIMEO, SNDTIMEO, RECONNECT_IVL, FD, TYPE, BACKLOG, RECONNECT_IVL_MAX, RCVHWM,
|
186
|
+
SNDHWM, RATE, RECOVERY_IVL, SNDBUF, RCVBUF, IPV4ONLY, ROUTER_BEHAVIOR, TCP_KEEPALIVE,
|
187
|
+
TCP_KEEPALIVE_CNT, TCP_KEEPALIVE_IDLE, TCP_KEEPALIVE_INTVL, TCP_ACCEPT_FILTER, MULTICAST_HOPS,
|
188
|
+
IMMEDIATE,
|
189
|
+
]
|
190
|
+
|
191
|
+
long_long_socket_options = [
|
192
|
+
RCVMORE, AFFINITY, MAXMSGSIZE,
|
193
|
+
]
|
194
|
+
|
195
|
+
string_socket_options = [
|
196
|
+
IDENTITY, SUBSCRIBE, UNSUBSCRIBE, LAST_ENDPOINT,
|
197
|
+
]
|
198
|
+
|
199
|
+
if LibZMQ.version4?
|
200
|
+
integer_socket_options += [
|
201
|
+
IPV6, MECHANISM, PLAIN_SERVER, CURVE_SERVER, PROBE_ROUTER, REQ_CORRELATE, REQ_RELAXED, CONFLATE,
|
202
|
+
]
|
203
|
+
|
204
|
+
string_socket_options += [
|
205
|
+
ZAP_DOMAIN, PLAIN_USERNAME, PLAIN_PASSWORD, CURVE_PUBLICKEY, CURVE_SERVERKEY, CURVE_SECRETKEY,
|
206
|
+
]
|
207
|
+
end
|
208
|
+
|
209
|
+
IntegerSocketOptions = integer_socket_options.sort
|
210
|
+
LongLongSocketOptions = long_long_socket_options.sort
|
211
|
+
StringSocketOptions = string_socket_options.sort
|
212
|
+
SocketOptions = (IntegerSocketOptions + LongLongSocketOptions + StringSocketOptions).sort
|
213
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
module LibC
|
3
|
+
extend FFI::Library
|
4
|
+
# figures out the correct libc for each platform including Windows
|
5
|
+
library = ffi_lib(FFI::Library::LIBC).first
|
6
|
+
|
7
|
+
# Size_t not working properly on Windows
|
8
|
+
find_type(:size_t) rescue typedef(:ulong, :size_t)
|
9
|
+
|
10
|
+
# memory allocators
|
11
|
+
attach_function :malloc, [:size_t], :pointer
|
12
|
+
attach_function :free, [:pointer], :void
|
13
|
+
|
14
|
+
# get a pointer to the free function; used for ZMQ::Message deallocation
|
15
|
+
Free = library.find_symbol('free')
|
16
|
+
|
17
|
+
# memory movers
|
18
|
+
attach_function :memcpy, [:pointer, :pointer, :size_t], :pointer
|
19
|
+
end # module LibC
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# Wraps the libzmq library and attaches to the functions that are
|
2
|
+
# common across the 3.2.x+ and 4.x APIs.
|
3
|
+
#
|
4
|
+
module LibZMQ
|
5
|
+
extend FFI::Library
|
6
|
+
|
7
|
+
begin
|
8
|
+
# bias the library discovery to a path inside the gem first, then
|
9
|
+
# to the usual system paths
|
10
|
+
inside_gem = File.join(File.dirname(__FILE__), '..', '..', 'ext')
|
11
|
+
local_path = FFI::Platform::IS_WINDOWS ? ENV['PATH'].split(';') : ENV['PATH'].split(':')
|
12
|
+
|
13
|
+
# Search for libzmq in the following order...
|
14
|
+
ZMQ_LIB_PATHS = ([inside_gem] + local_path + [
|
15
|
+
'/usr/local/lib', '/opt/local/lib', '/usr/local/homebrew/lib', '/usr/lib64'
|
16
|
+
]).map{|path| "#{path}/libzmq.#{FFI::Platform::LIBSUFFIX}"}
|
17
|
+
ffi_lib(ZMQ_LIB_PATHS + %w{libzmq})
|
18
|
+
|
19
|
+
rescue LoadError
|
20
|
+
if ZMQ_LIB_PATHS.any? {|path|
|
21
|
+
File.file? File.join(path, "libzmq.#{FFI::Platform::LIBSUFFIX}")}
|
22
|
+
warn "Unable to load this gem. The libzmq library exists, but cannot be loaded."
|
23
|
+
warn "If this is Windows:"
|
24
|
+
warn "- Check that you have MSVC runtime installed or statically linked"
|
25
|
+
warn "- Check that your DLL is compiled for #{FFI::Platform::ADDRESS_SIZE} bit"
|
26
|
+
else
|
27
|
+
warn "Unable to load this gem. The libzmq library (or DLL) could not be found."
|
28
|
+
warn "If this is a Windows platform, make sure libzmq.dll is on the PATH."
|
29
|
+
warn "If the DLL was built with mingw, make sure the other two dependent DLLs,"
|
30
|
+
warn "libgcc_s_sjlj-1.dll and libstdc++6.dll, are also on the PATH."
|
31
|
+
warn "For non-Windows platforms, make sure libzmq is located in this search path:"
|
32
|
+
warn ZMQ_LIB_PATHS.inspect
|
33
|
+
end
|
34
|
+
raise LoadError, "The libzmq library (or DLL) could not be loaded"
|
35
|
+
end
|
36
|
+
|
37
|
+
# Size_t not working properly on Windows
|
38
|
+
find_type(:size_t) rescue typedef(:ulong, :size_t)
|
39
|
+
|
40
|
+
# Context and misc api
|
41
|
+
#
|
42
|
+
# @blocking = true is a hint to FFI that the following (and only the following)
|
43
|
+
# function may block, therefore it should release the GIL before calling it.
|
44
|
+
# This can aid in situations where the function call will/may block and another
|
45
|
+
# thread within the lib may try to call back into the ruby runtime. Failure to
|
46
|
+
# release the GIL will result in a hang; the hint is required for MRI otherwise
|
47
|
+
# there are random hangs (which require kill -9 to terminate).
|
48
|
+
#
|
49
|
+
attach_function :zmq_version, [:pointer, :pointer, :pointer], :void, :blocking => true
|
50
|
+
attach_function :zmq_errno, [], :int, :blocking => true
|
51
|
+
attach_function :zmq_strerror, [:int], :pointer, :blocking => true
|
52
|
+
|
53
|
+
# Context initialization and destruction
|
54
|
+
attach_function :zmq_init, [:int], :pointer, :blocking => true
|
55
|
+
attach_function :zmq_term, [:pointer], :int, :blocking => true
|
56
|
+
attach_function :zmq_ctx_new, [], :pointer, :blocking => true
|
57
|
+
attach_function :zmq_ctx_destroy, [:pointer], :int, :blocking => true
|
58
|
+
attach_function :zmq_ctx_set, [:pointer, :int, :int], :int, :blocking => true
|
59
|
+
attach_function :zmq_ctx_get, [:pointer, :int], :int, :blocking => true
|
60
|
+
|
61
|
+
# Message API
|
62
|
+
attach_function :zmq_msg_init, [:pointer], :int, :blocking => true
|
63
|
+
attach_function :zmq_msg_init_size, [:pointer, :size_t], :int, :blocking => true
|
64
|
+
attach_function :zmq_msg_init_data, [:pointer, :pointer, :size_t, :pointer, :pointer], :int, :blocking => true
|
65
|
+
attach_function :zmq_msg_close, [:pointer], :int, :blocking => true
|
66
|
+
attach_function :zmq_msg_data, [:pointer], :pointer, :blocking => true
|
67
|
+
attach_function :zmq_msg_size, [:pointer], :size_t, :blocking => true
|
68
|
+
attach_function :zmq_msg_copy, [:pointer, :pointer], :int, :blocking => true
|
69
|
+
attach_function :zmq_msg_move, [:pointer, :pointer], :int, :blocking => true
|
70
|
+
attach_function :zmq_msg_send, [:pointer, :pointer, :int], :int, :blocking => true
|
71
|
+
attach_function :zmq_msg_recv, [:pointer, :pointer, :int], :int, :blocking => true
|
72
|
+
attach_function :zmq_msg_more, [:pointer], :int, :blocking => true
|
73
|
+
attach_function :zmq_msg_get, [:pointer, :int], :int, :blocking => true
|
74
|
+
attach_function :zmq_msg_set, [:pointer, :int, :int], :int, :blocking => true
|
75
|
+
|
76
|
+
# Socket API
|
77
|
+
attach_function :zmq_socket, [:pointer, :int], :pointer, :blocking => true
|
78
|
+
attach_function :zmq_setsockopt, [:pointer, :int, :pointer, :int], :int, :blocking => true
|
79
|
+
attach_function :zmq_getsockopt, [:pointer, :int, :pointer, :pointer], :int, :blocking => true
|
80
|
+
attach_function :zmq_bind, [:pointer, :string], :int, :blocking => true
|
81
|
+
attach_function :zmq_connect, [:pointer, :string], :int, :blocking => true
|
82
|
+
attach_function :zmq_close, [:pointer], :int, :blocking => true
|
83
|
+
|
84
|
+
# Device API
|
85
|
+
attach_function :zmq_proxy, [:pointer, :pointer, :pointer], :int, :blocking => true
|
86
|
+
|
87
|
+
# Poll API
|
88
|
+
attach_function :zmq_poll, [:pointer, :int, :long], :int, :blocking => true
|
89
|
+
|
90
|
+
# Monitoring API
|
91
|
+
attach_function :zmq_socket_monitor, [:pointer, :pointer, :int], :int, :blocking => true
|
92
|
+
|
93
|
+
# Socket API
|
94
|
+
attach_function :zmq_unbind, [:pointer, :string], :int, :blocking => true
|
95
|
+
attach_function :zmq_disconnect, [:pointer, :string], :int, :blocking => true
|
96
|
+
attach_function :zmq_recvmsg, [:pointer, :pointer, :int], :int, :blocking => true
|
97
|
+
attach_function :zmq_recv, [:pointer, :pointer, :size_t, :int], :int, :blocking => true
|
98
|
+
attach_function :zmq_sendmsg, [:pointer, :pointer, :int], :int, :blocking => true
|
99
|
+
attach_function :zmq_send, [:pointer, :pointer, :size_t, :int], :int, :blocking => true
|
100
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module LibZMQ
|
2
|
+
|
3
|
+
# Used for casting pointers back to the msg_t struct
|
4
|
+
#
|
5
|
+
class Msg < FFI::Struct
|
6
|
+
layout :content, :pointer,
|
7
|
+
:flags, :uint8,
|
8
|
+
:vsm_size, :uint8,
|
9
|
+
:vsm_data, [:uint8, 30]
|
10
|
+
end # class Msg
|
11
|
+
|
12
|
+
|
13
|
+
# Create the basic mapping for the poll_item_t structure so we can
|
14
|
+
# access those fields via Ruby.
|
15
|
+
#
|
16
|
+
module PollItemLayout
|
17
|
+
def self.included(base)
|
18
|
+
fd_type = if FFI::Platform::IS_WINDOWS && FFI::Platform::ADDRESS_SIZE == 64
|
19
|
+
# On Windows, zmq.h defines fd as a SOCKET, which is 64 bits on x64.
|
20
|
+
:uint64
|
21
|
+
else
|
22
|
+
:int
|
23
|
+
end
|
24
|
+
|
25
|
+
base.class_eval do
|
26
|
+
layout :socket, :pointer,
|
27
|
+
:fd, fd_type,
|
28
|
+
:events, :short,
|
29
|
+
:revents, :short
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
# PollItem class includes the PollItemLayout module so that we can use the
|
36
|
+
# basic FFI accessors to get at the structure's fields. We also want to provide
|
37
|
+
# some higher-level Ruby accessors for convenience.
|
38
|
+
#
|
39
|
+
class PollItem < FFI::Struct
|
40
|
+
include PollItemLayout
|
41
|
+
|
42
|
+
def socket
|
43
|
+
self[:socket]
|
44
|
+
end
|
45
|
+
|
46
|
+
def fd
|
47
|
+
self[:fd]
|
48
|
+
end
|
49
|
+
|
50
|
+
def readable?
|
51
|
+
(self[:revents] & ZMQ::POLLIN) > 0
|
52
|
+
end
|
53
|
+
|
54
|
+
def writable?
|
55
|
+
(self[:revents] & ZMQ::POLLOUT) > 0
|
56
|
+
end
|
57
|
+
|
58
|
+
def inspect
|
59
|
+
"socket [#{socket}], fd [#{fd}], events [#{self[:events]}], revents [#{self[:revents]}]"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
# /* Socket event data */
|
65
|
+
# typedef struct {
|
66
|
+
# uint16_t event; // id of the event as bitfield
|
67
|
+
# int32_t value ; // value is either error code, fd or reconnect interval
|
68
|
+
# } zmq_event_t;
|
69
|
+
module EventDataLayout
|
70
|
+
def self.included(base)
|
71
|
+
base.class_eval do
|
72
|
+
layout :event, :uint16,
|
73
|
+
:value, :int32
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end # module EventDataLayout
|
77
|
+
|
78
|
+
|
79
|
+
# Provide a few convenience methods for accessing the event structure.
|
80
|
+
#
|
81
|
+
class EventData < FFI::Struct
|
82
|
+
include EventDataLayout
|
83
|
+
|
84
|
+
def event
|
85
|
+
self[:event]
|
86
|
+
end
|
87
|
+
|
88
|
+
def value
|
89
|
+
self[:value]
|
90
|
+
end
|
91
|
+
|
92
|
+
def inspect
|
93
|
+
"event [#{event}], value [#{value}]"
|
94
|
+
end
|
95
|
+
end # class EventData
|
96
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
module LibZMQ
|
3
|
+
|
4
|
+
# Returns a hash of the form {:major => X, :minor => Y, :patch => Z} to represent the
|
5
|
+
# version of libzmq.
|
6
|
+
#
|
7
|
+
# Class method.
|
8
|
+
#
|
9
|
+
# Invoke as: ZMQ::LibZMQ.version
|
10
|
+
#
|
11
|
+
def self.version
|
12
|
+
unless @version
|
13
|
+
major = FFI::MemoryPointer.new :int
|
14
|
+
minor = FFI::MemoryPointer.new :int
|
15
|
+
patch = FFI::MemoryPointer.new :int
|
16
|
+
LibZMQ.zmq_version major, minor, patch
|
17
|
+
@version = {:major => major.read_int, :minor => minor.read_int, :patch => patch.read_int}
|
18
|
+
end
|
19
|
+
|
20
|
+
@version
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.version3?
|
24
|
+
version[:major] == 3 && version[:minor] >= 2
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.version4?
|
28
|
+
version[:major] == 4
|
29
|
+
end
|
30
|
+
|
31
|
+
# Sanity check; print an error and exit if we are trying to load an unsupported
|
32
|
+
# version of libzmq.
|
33
|
+
#
|
34
|
+
hash = LibZMQ.version
|
35
|
+
major, minor = hash[:major], hash[:minor]
|
36
|
+
if major < 3 || (major == 3 && minor < 2)
|
37
|
+
version = "#{hash[:major]}.#{hash[:minor]}.#{hash[:patch]}"
|
38
|
+
raise LoadError, "The libzmq version #{version} is incompatible with this version of ffi-rzmq-core."
|
39
|
+
end
|
40
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ffi-rzmq-core
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chuck Remes
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-11-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ffi
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.9'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.9'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.14'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.14'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: |-
|
56
|
+
This gem provides only the FFI wrapper for the ZeroMQ (0mq) networking library.
|
57
|
+
Project can be used by any other zeromq gems that want to provide their own high-level Ruby API.
|
58
|
+
email:
|
59
|
+
- git@chuckremes.com
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- .gitignore
|
65
|
+
- .travis.yml
|
66
|
+
- LICENSE
|
67
|
+
- README.md
|
68
|
+
- ffi-rzmq-core.gemspec
|
69
|
+
- lib/ffi-rzmq-core.rb
|
70
|
+
- lib/ffi-rzmq-core/constants.rb
|
71
|
+
- lib/ffi-rzmq-core/libc.rb
|
72
|
+
- lib/ffi-rzmq-core/libzmq.rb
|
73
|
+
- lib/ffi-rzmq-core/structures.rb
|
74
|
+
- lib/ffi-rzmq-core/utilities.rb
|
75
|
+
- lib/ffi-rzmq-core/version.rb
|
76
|
+
- spec/spec_helper.rb
|
77
|
+
homepage: http://github.com/chuckremes/ffi-rzmq-core
|
78
|
+
licenses:
|
79
|
+
- MIT
|
80
|
+
metadata: {}
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 2.0.3
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: This gem provides only the FFI wrapper for the ZeroMQ (0mq) networking library.
|
101
|
+
test_files:
|
102
|
+
- spec/spec_helper.rb
|