SWIG: ruby proc->c function pointer

Discussion in 'Ruby' started by gga, Jan 28, 2005.

  1. gga

    gga Guest

    Sorry for the slightly off-topic question. I am starting to use swig
    to wrap some C++ library for ruby for the first time.
    In the process of doing so, I realize I will need to pass proc objects
    from ruby and turn them into function pointers in C, so as to provide a
    callback mechanism.
    I understand this can potentially be done with typemaps, but I am not
    sure exactly how. I only need to have a single callback per class, so
    I was thinking of storing the ruby callback within the class itself and
    then have a common C wrap function that would map the C callback to the
    appropiate ruby callbacks (ie. proc object) based on what was stored in
    the class. I was also unsure if SWIG already provides some auxiliary
    functions for doing something similar.
    Does anyone have any pointers?
    I'm already familiar with how ruby-fltk handles this, for example, and
    I want to basically emulate something akin within the SWIG
    meta-language. I'm looking at FXRuby but the code is a tad too complex
    for a SWIG newbie.
     
    gga, Jan 28, 2005
    #1
    1. Advertising

  2. gga

    Kouhei Sutou Guest

    Hi,

    I'm writing bindings to Subversion by SWIG. This has some
    callback codes.

    In <>
    "SWIG: ruby proc->c function pointer" on Sat, 29 Jan 2005 03:25:52 +0900,
    "gga" <> wrote:

    > In the process of doing so, I realize I will need to pass proc objects
    > from ruby and turn them into function pointers in C, so as to provide a
    > callback mechanism.


    Here is an example:

    --- callback.h
    #ifndef CALLBACK_H
    #define CALLBACK_H

    typedef void (*callback_t) (void *user_data, const char *other_data);

    void invoke(callback_t callback, void *user_data, const char *other_data);

    #endif
    ---

    --- callback.c
    #include "callback.h"

    void
    invoke(callback_t callback, void *user_data, const char *other_data)
    {
    callback(user_data, other_data);
    }
    ---

    --- callback.i
    %module callback

    %{
    void
    wrap_callback(void *user_data, const char *other_data)
    {
    VALUE proc = (VALUE)user_data;
    rb_funcall(proc, rb_intern("call"), 1, rb_str_new2(other_data));
    }
    %}

    %typemap(in) (callback_t callback, void *user_data)
    {
    $1 = wrap_callback;
    $2 = (void *)$input;
    }

    %include callback.h
    %{
    #include "callback.h"
    %}
    ---

    --- Makefile.swig
    # -*- Makefile -*-

    MODULE = callback
    FEATURE = $(MODULE)
    INTERFACE = $(MODULE).i

    RUBY = ruby
    SWIG = swig

    SWIGOPT = -I/usr/local/include -I/usr/include -ruby -feature $(FEATURE)
    WRAPPER = $(FEATURE)_wrap.c

    swigall: $(WRAPPER) Makefile

    $(WRAPPER): $(INTERFACE)
    $(SWIG) $(SWIGOPT) -o $@ $(INTERFACE)

    Makefile: extconf.rb
    $(RUBY) extconf.rb
    @if [ -f Makefile ] ; then\
    echo "include Makefile.swig" >> Makefile;\
    fi

    swigclean:
    @if [ -f Makefile ] ; then\
    make -f Makefile clean;\
    fi
    rm -f Makefile $(WRAPPER)
    ---

    --- extconf.rb
    require 'mkmf'
    create_makefile("callback")
    ---

    --- to build
    % make -f Makefile.swig
    % make
    ---

    --- sample usage
    % irb -r callback
    irb(main):001:0> Callback.invoke(Proc.new{|str| p str}, "abc")
    "abc"
    => nil
    ---

    --
    kou
     
    Kouhei Sutou, Jan 29, 2005
    #2
    1. Advertising

  3. gga

    gga Guest

    I finally got around to trying this. Thanks.
    Unfortunately, the latest SWIG (v1.3.22) seems to choke on it, with:

    irb(main):005:0> Callback.invoke(Proc.new{|str| p str}, "abc")
    TypeError: cannot convert nil into String
    from (irb):5:in `invoke'
    from (irb):5

    Looking at the code, SWIG fails in the StringValuePtr() conversion
    here.

    /* Get type mangle from class name */
    SWIGRUNTIME(char *)
    SWIG_Ruby_MangleStr(VALUE obj)
    {
    VALUE stype = rb_iv_get(obj, "__swigtype__");
    return StringValuePtr(stype);
    }
     
    gga, Feb 17, 2005
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. David Lozzi
    Replies:
    3
    Views:
    1,993
    David Lozzi
    Jun 1, 2005
  2. glen stark
    Replies:
    2
    Views:
    728
    Ron Natalie
    Oct 10, 2003
  3. NevilleDNZ
    Replies:
    9
    Views:
    462
    NevilleDNZ
    Aug 16, 2006
  4. Jean-Hugues ROBERT

    Why no Proc##[]=() ? Why no Proc##replace() ?

    Jean-Hugues ROBERT, May 1, 2004, in forum: Ruby
    Replies:
    14
    Views:
    315
    Jean-Hugues ROBERT
    May 5, 2004
  5. Minkoo Seo

    Proc vs lambda vs proc

    Minkoo Seo, Feb 4, 2007, in forum: Ruby
    Replies:
    19
    Views:
    262
    Brian Candler
    Feb 6, 2007
Loading...

Share This Page