Subject: [ruby-ffi] pointers and out parameters |
From: Mark Wotton |
Date: 1/19/12 1:40 AM |
To: ruby-ffi |
Hi all,
I'm trying to move some code from C to Ruby using FFI.
The problematic chunk looks like this:
int verbose = (argc > 1 && streq (argv [1], "-v"));
mdwrk_t *session = mdwrk_new (
"tcp://localhost:5555", "echo", verbose);
zmsg_t *reply = NULL;
while (1) {
zmsg_t *request = mdwrk_recv (session, &reply);
if (request == NULL)
break; // Worker was interrupted
reply = request; // Echo is complex... :-)
}
mdwrk_destroy (&session);
return 0;
I'm not quite sure how to model the "reply = request" chunk - I have
this:
module Majordomo
extend FFI::Library
ffi_lib 'lib0mq_majordomo'
attach_function :mdwrk_new, [:string, :string, :bool], :pointer
attach_function :mdwrk_recv, [:pointer, :pointer], :pointer
attach_function :mdwrk_destroy, [:pointer], :void
class Worker < FFI::ManagedStruct
def initialize(host, service, verbose=false)
@session = Majordomo.mdwrk_new host, service, verbose
end
# this is a bit ugly, but the C expects to be in a run loop
# and therefore makes mdwrk_recv do two things...
def once
raise "Worker needs a responder block" unless block_given?
ptr = FFI::MemoryPointer.new(:pointer)
while true
puts "calling receive"
request = Majordomo.mdwrk_recv @session, ptr
puts "worker interrupted" unless request
ptr = yield request
end
end
end
end
calling it as
while true
worker.once {|x|
x}
end
to test. The first run goes through ok, but the "ptr = yield request"
is clearly bogus: it should really be one layer of indirection out.
I can't see how to model this, even after going through the out
parameter section in the wiki. Could you help?
cheers
Mark