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