Revision: 7655
          http://playerstage.svn.sourceforge.net/playerstage/?rev=7655&view=rev
Author:   robotos
Date:     2009-05-14 03:14:25 +0000 (Thu, 14 May 2009)

Log Message:
-----------
Ruby bindings. 
As the bindings/CMakeList.txt is not modified this directory will not be 
compiled by default
In my system thought they work not completely but without breakage. 

This bindings use the same procedure than the Python bindings. Thanks for that.

Added Paths:
-----------
    code/player/trunk/client_libs/libplayerc/bindings/ruby/
    code/player/trunk/client_libs/libplayerc/bindings/ruby/CMakeLists.txt
    code/player/trunk/client_libs/libplayerc/bindings/ruby/README
    code/player/trunk/client_libs/libplayerc/bindings/ruby/TODO
    code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/
    code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/laser.rb
    code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/test.rb
    
code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/test_bindings_installation.rb
    code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/wifi.rb
    code/player/trunk/client_libs/libplayerc/bindings/ruby/libplayerc_rb.html
    code/player/trunk/client_libs/libplayerc/bindings/ruby/playerc.i
    code/player/trunk/client_libs/libplayerc/bindings/ruby/playerc_swig_parse.py

Added: code/player/trunk/client_libs/libplayerc/bindings/ruby/CMakeLists.txt
===================================================================
--- code/player/trunk/client_libs/libplayerc/bindings/ruby/CMakeLists.txt       
                        (rev 0)
+++ code/player/trunk/client_libs/libplayerc/bindings/ruby/CMakeLists.txt       
2009-05-14 03:14:25 UTC (rev 7655)
@@ -0,0 +1,77 @@
+INCLUDE (FindPythonInterp)
+IF (PYTHONINTERP_FOUND)
+    OPTION (BUILD_RUBY_BINDINGS "Build the Ruby bindings for the C client 
library" ON)
+
+    IF (BUILD_RUBY_BINDINGS)
+        FIND_PACKAGE (SWIG)
+        IF (SWIG_FOUND)
+            MESSAGE (STATUS "Python bindings for C client library will be 
built")
+
+            INCLUDE (${SWIG_USE_FILE})
+
+            FIND_PACKAGE (Ruby)
+            INCLUDE_DIRECTORIES (${RUBY_INCLUDE_PATH})
+            INCLUDE_DIRECTORIES (${PROJECT_SOURCE_DIR})
+            INCLUDE_DIRECTORIES (${PROJECT_BINARY_DIR})
+            INCLUDE_DIRECTORIES (${PROJECT_SOURCE_DIR}/client_libs/libplayerc)
+
+            SET (CMAKE_SWIG_FLAGS "")
+
+            # Generate playerc_wrap.i and playerc_wrap.h from playerc.h
+            SET (playerc_wrap_prefix 
"${CMAKE_CURRENT_BINARY_DIR}/playerc_wrap")
+            ADD_CUSTOM_COMMAND (OUTPUT "${playerc_wrap_prefix}.i"
+                COMMAND ${PYTHON_EXECUTABLE} 
${CMAKE_CURRENT_SOURCE_DIR}/playerc_swig_parse.py 
${PROJECT_SOURCE_DIR}/client_libs/libplayerc/playerc.h ${playerc_wrap_prefix}
+                WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+                VERBATIM)
+
+            ADD_CUSTOM_COMMAND(OUTPUT "${playerc_wrap_prefix}.h"
+                DEPENDS "${playerc_wrap_prefix}.i")
+
+            # Empty target to ensure playerc_wrap.i and playerc_wrap.h get 
created
+            ADD_CUSTOM_TARGET (playerc_wrap_ri_target ALL
+                DEPENDS "${playerc_wrap_prefix}.i"
+                DEPENDS "${playerc_wrap_prefix}.h")
+
+            # Copy playerc.i to the build directory
+            SET (playerc_i_in "${CMAKE_CURRENT_SOURCE_DIR}/playerc.i")
+            SET (playerc_i "${CMAKE_CURRENT_BINARY_DIR}/playerc.i")
+            CONFIGURE_FILE (${playerc_i_in} ${playerc_i} COPYONLY)
+
+            #If playercr is called simply playerc, all sorts of errors happen
+            #I guess is namespace conflict with Python bindings' playerc
+            #currently we create playercr locally but install it as playerc 
+            SWIG_ADD_MODULE (playercr ruby ${playerc_i})
+            SWIG_LINK_LIBRARIES (playercr ${RUBY_LIBRARY})
+            ADD_DEPENDENCIES (${SWIG_MODULE_playercr_REAL_NAME} 
playerc_wrap_i_target)
+            TARGET_LINK_LIBRARIES (${SWIG_MODULE_playercr_REAL_NAME} playerxdr 
playerc playererror)
+            IF (HAVE_JPEG)
+                TARGET_LINK_LIBRARIES (${SWIG_MODULE_playercr_REAL_NAME} 
playerjpeg)
+            ENDIF (HAVE_JPEG)
+
+            #TODO: find ruby in windows, check install dir is correct
+            IF (PYTHON_OS_WIN)
+                GET_FILENAME_COMPONENT (playercruInstallDir ${RUBY_EXECUTABLE} 
PATH)
+            ELSE (PYTHON_OS_WIN)
+                # Get the Python version
+                EXECUTE_PROCESS (COMMAND ${PYTHON_EXECUTABLE} -V
+                                 ERROR_VARIABLE pythonVersionString
+                                 ERROR_STRIP_TRAILING_WHITESPACE)
+                STRING (REGEX REPLACE "^Python ([0-9]+\\.[0-9]+).*" "\\1" 
pythonVersion ${pythonVersionString})
+                SET (playercruInstallDir 
lib/python${pythonVersion}/site-packages)
+            ENDIF (PYTHON_OS_WIN)
+            SET (RUBY_BINDINGS_INSTALL_DIR ${playercruInstallDir} CACHE PATH 
"Ruby bindings installation directory under $prefix")
+            MARK_AS_ADVANCED (RUBY_BINDINGS_INSTALL_DIR)
+
+            INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/playercr.so
+                DESTINATION ${RUBY_SITELIB_DIR}
+                RENAME playerc.so)
+        ELSE (SWIG_FOUND)
+            MESSAGE (STATUS "Ruby bindings for C client library will not be 
built - could not find Swig")
+        ENDIF (SWIG_FOUND)
+    ELSE (BUILD_RUBY_BINDINGS)
+        MESSAGE (STATUS "Ruby bindings for C client library will not be built 
- disabled by user")
+    ENDIF (BUILD_RUBY_BINDINGS)
+ELSE (PYTHONINTERP_FOUND)
+    MESSAGE (STATUS "Ruby bindings for C client library will not be built - 
could not find Python")
+ENDIF (PYTHONINTERP_FOUND)
+

Added: code/player/trunk/client_libs/libplayerc/bindings/ruby/README
===================================================================
--- code/player/trunk/client_libs/libplayerc/bindings/ruby/README               
                (rev 0)
+++ code/player/trunk/client_libs/libplayerc/bindings/ruby/README       
2009-05-14 03:14:25 UTC (rev 7655)
@@ -0,0 +1,28 @@
+These are the Ruby bindings for Player (part of the PlayerStage project).
+http://playerstage.sourceforge.net/
+
+THIS BINDINGS WILL NOT BE COMPILED BY DEFAULT!
+
+If you want to install this bindings edit the CMakeList file on 
+$PLAYER_SOURCES_ROOT/client_libs/libplayerc/bindings/CMakefile.txt
+
+
+This is a work in progress, examples in examples/  
+show what is hopefully working so far. 
+
+The ruby examples connect to a local Player running in the default port. 
+Start Player before running any examples.
+The examples will access underlying hardware so either you have Player running 
in the real robotic hardware
+or read Player documentation to run Player with the Stage or Gazebo 
simulators. 
+
+For instance, laser.rb can be run with Player and Gazebo as follows:
+
+gazebo worlds/pioneer2dx.cfg
+player GAZEBO_ROOT/player-cfgs/gazebo.cfg
+ruby test.rb laser
+
+Gazebo provides of an environment with an specific robot and laser (defined in 
pioneer2dx.cfg)
+Player connects to gazebo and provides of robot and laser generic interfaces 
(defined in gazebo.cfg)
+laser.rb controls a generic robot with a generic laser
+
+

Added: code/player/trunk/client_libs/libplayerc/bindings/ruby/TODO
===================================================================
--- code/player/trunk/client_libs/libplayerc/bindings/ruby/TODO                 
        (rev 0)
+++ code/player/trunk/client_libs/libplayerc/bindings/ruby/TODO 2009-05-14 
03:14:25 UTC (rev 7655)
@@ -0,0 +1,7 @@
+Test:
+  use wifi.rb to test uint8_t arrays (stage support wifi devices?
+  double arrays of arrays (other double arrays are needed?)
+  rfid tags
+  catch-all rule
+
+  c to ruby communication

Added: code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/laser.rb
===================================================================
--- code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/laser.rb    
                        (rev 0)
+++ code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/laser.rb    
2009-05-14 03:14:25 UTC (rev 7655)
@@ -0,0 +1,78 @@
+#This file is equivalent to playercpy_example.py of the Python bindings
+#If the behaviour is not the same, something went wrong!
+
+require 'playerc'
+
+class PlayercExamples 
+
+  def laser
+
+    position = Playerc::Playerc_position2d.new(@connection, 0)
+    if position.subscribe(Playerc::PLAYER_OPEN_MODE) != 0
+      raise  Playerc::playerc_error_str()
+    end
+
+    # Retrieve the robot geometry
+    if position.get_geom != 0
+      raise Playerc::playerc_error_str()
+    end
+
+    puts "Robot size:  #{position.size[0]}  #{position.size[1]} "
+
+     # Create a proxy for laser:0
+    laser = Playerc::Playerc_laser.new(@connection, 0)
+    if laser.subscribe(Playerc::PLAYER_OPEN_MODE) != 0
+      raise  Playerc::playerc_error_str()
+    end
+
+    # Retrieve the laser geometry
+    if laser.get_geom != 0:
+      raise Playerc::playerc_error_str
+    end
+    puts "Laser pose: (%.3f, %.3f, %.3f)" % laser.pose 
+    # Start the robot turning CCW at 20 deg / sec
+    position.set_cmd_vel(0.0, 0.0, 20.0 * Math::PI / 180.0, 1)
+
+    for i in 0..30 do
+      if @connection.read.nil?
+        raise Playerc::playerc_error_str()
+      end
+
+      puts "Robot pose: (%.3f,%.3f,%.3f)" % [position.px, position.py, 
position.pa]
+
+      laserscanstr = 'Partial laser scan: '
+      for j in 0..5 do
+        break if j >= laser.scan_count
+        laserscanstr += '%.3f ' % laser.ranges[j]
+      end
+     puts laserscanstr
+     #times and scan counts
+#     puts "laser datatime, scan count: (%14.3f) (%d)" % [laser.info.datatime, 
laser.scan_count]
+#     puts " "
+    end
+
+    # Turn the other way
+    position.set_cmd_vel(0.0, 0.0, -20.0 * Math::PI / 180.0, 1)
+
+    for i in 0..30 do
+      if @connection.read.nil?
+        raise Playerc::playerc_error_str()
+      end
+      puts "Robot pose: (%.3f,%.3f,%.3f)" % 
[position.px,position.py,position.pa]
+      laserscanstr = 'Partial laser scan: '
+      for j in 0..5 do
+        break if j >= laser.scan_count
+        laserscanstr += '%.3f ' % laser.ranges[j]
+      end
+      puts laserscanstr
+    end
+
+    # Now stop
+    position.set_cmd_vel(0.0, 0.0, 0.0, 1)
+
+    # Clean up
+    laser.unsubscribe()
+    position.unsubscribe()
+
+  end
+end

Added: code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/test.rb
===================================================================
--- code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/test.rb     
                        (rev 0)
+++ code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/test.rb     
2009-05-14 03:14:25 UTC (rev 7655)
@@ -0,0 +1,44 @@
+#!/usr/bin/ruby
+
+require 'playerc'
+require 'laser'
+require 'wifi'
+
+ 
+
+class PlayercExamples
+  def initialize 
+    @connection = Playerc::Playerc_client.new(nil, 'localhost', 6665)
+    if @connection.connect != 0
+      raise Playerc::playerc_error_str()
+    end
+  end
+
+  def finish
+    @connection.disconnect()
+  end
+end
+
+
+examples = PlayercExamples.new
+tests = []
+
+ARGV.each do|a|
+  if (a == "all")
+    tests = examples.public_methods false
+  else
+    if examples.respond_to?(a.to_sym)
+      tests.push(a)
+    else
+      puts "requested test #{a} doesn't exist"
+    end
+  end
+end
+
+tests.each do |test|
+  examples.send(test.to_sym)
+end
+
+examples.finish
+
+

Added: 
code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/test_bindings_installation.rb
===================================================================
--- 
code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/test_bindings_installation.rb
                               (rev 0)
+++ 
code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/test_bindings_installation.rb
       2009-05-14 03:14:25 UTC (rev 7655)
@@ -0,0 +1,24 @@
+#!/usr/bin/ruby
+
+def error
+  puts "Player bindings not installed"
+end
+
+begin
+  
+  require 'playerc'
+
+  if Playerc::constants.size > 0
+    puts "Player bindings are installed"
+    classes = Playerc.constants.select {|c| Class === Playerc.const_get(c)}
+#    puts classes
+  else
+    error
+  end
+rescue LoadError
+  error
+rescue
+  error
+end
+
+


Property changes on: 
code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/test_bindings_installation.rb
___________________________________________________________________
Added: svn:executable
   + *

Added: code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/wifi.rb
===================================================================
--- code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/wifi.rb     
                        (rev 0)
+++ code/player/trunk/client_libs/libplayerc/bindings/ruby/examples/wifi.rb     
2009-05-14 03:14:25 UTC (rev 7655)
@@ -0,0 +1,34 @@
+
+require 'playerc'
+
+class PlayercExamples
+
+  def wifi
+
+    wifi = Playerc::Playerc_wifi.new(@connection, 0)
+
+    #for i in range(device.link_count + 10):
+    #    link = playerc_wifi_get_link(device, i)
+    #    #print '[%s] [%d]' % (link.mac, link.level)
+
+    link = wifi.get_link(0)
+    puts 'wifi mac: [%s], ip [%s], essid [%s], wifi level: [%d]' % [link.mac, 
link.ip, link.essid, link.level] unless link.nil?
+
+    if wifi.subscribe( Playerc::PLAYERC_OPEN_MODE) != 0 
+      raise Playerc::playerc_error_str
+    end
+
+
+    for i in 0..5 do
+      if @connection.read.nil?
+        raise Playerc::playerc_error_str()
+      end
+      puts wifi.scan
+      for link in device.links do
+        puts "wifi: [%d] [%s] [%s] [%s] [%4d] [%4d]" % \
+          [i, link.mac, link.essid, link.ip, link.level, link.noise]
+      end
+    end
+
+  end
+end

Added: code/player/trunk/client_libs/libplayerc/bindings/ruby/libplayerc_rb.html
===================================================================
--- code/player/trunk/client_libs/libplayerc/bindings/ruby/libplayerc_rb.html   
                        (rev 0)
+++ code/player/trunk/client_libs/libplayerc/bindings/ruby/libplayerc_rb.html   
2009-05-14 03:14:25 UTC (rev 7655)
@@ -0,0 +1,19 @@
+/** @ingroup clientlibs
+    @defgroup player_clientlib_libplayerc_rb libplayerc_rb
+    @brief A Ruby client library for the @ref util_player
+
+    libplayerc_rb is a SWIG-generated Ruby interface to @ref
+    player_clientlib_libplayerc.  You can guess the Ruby API by a little
+    mental translation of the symbol names in the C API.
+
+    For now, check out the @ref libplayerc_rb_example "example".
+
+    @todo Document this library properly.
+*/
+
+/** @ingroup player_clientlib_libplayerc_ru
+    @defgroup libplayerc_rb_example libplayerc_rb example
+    @brief An example of using libplayerc_rb
+
+    @include playercrb_example.rb
+*/

Added: code/player/trunk/client_libs/libplayerc/bindings/ruby/playerc.i
===================================================================
--- code/player/trunk/client_libs/libplayerc/bindings/ruby/playerc.i            
                (rev 0)
+++ code/player/trunk/client_libs/libplayerc/bindings/ruby/playerc.i    
2009-05-14 03:14:25 UTC (rev 7655)
@@ -0,0 +1,322 @@
+
+%module playerc
+
+%{
+#include "playerc_wrap.h"
+
+%}
+
+%include "typemaps.i"
+
+
+// For playerc_simulation_get_pose2d()
+%apply double *OUTPUT { double *x, double *y, double *a };
+
+
+/******************************************
+
+     C to RUBY  (Ruby reads)
+ $1 C types
+ $result Ruby types
+
+******************************************/
+
+
+
+// C to RUBY (ruby reads) basic types
+//TODO: the unsigned long long stuff is correct?
+%typemap(out) uint8_t
+{
+  $result = UINT2NUM((unsigned char) $1);
+}
+
+%typemap(out) uint16_t
+{
+  $result = UINT2NUM((unsigned long) $1);
+}
+
+%typemap(out) uint32_t
+{
+  $result = UINT2NUM((long) (unsigned long long) $1);
+}
+
+
+
+
+
+// Provide array access
+%typemap(out) double [ANY]
+{
+  VALUE ary;
+  int i;
+  ary =rb_ary_new2($1_dim0);
+  for (i = 0; i < $1_dim0; i++)
+  {
+    rb_ary_push(ary, rb_float_new((double)$1[i])); 
+  }
+  $result = ary;
+}
+
+%typemap(out) float [ANY]
+{
+  VALUE ary;
+  int i;
+  ary =rb_ary_new2($1_dim0);
+  for (i = 0; i < $1_dim0; i++)
+  {
+    rb_ary_push(ary, rb_float_new((float)$1[i])); 
+  }
+  $result = ary;
+}
+
+
+
+%typemap(out) uint8_t [ANY]
+{
+  VALUE ary;
+  int i;
+  ary =rb_ary_new2($1_dim0);
+  for (i = 0; i < $1_dim0; i++)
+  {
+    rb_ary_push(ary, INT2FIX($1[i]));
+  }
+  $result = ary;
+}
+
+
+// Provide array access doubly-dimensioned arrays
+%typemap(out) double [ANY] [ANY]
+{
+    VALUE ary;
+    int i,j;
+    ary = rb_ary_new2($1_dim0);
+    for (i = 0; i < $1_dim0; i++)
+    {
+        inner_ary =  rb_ary_new2($1_dim0);
+        for (j = 0; j < $1_dim1; j++)
+        {
+            rb_ary_push(inner_ary, rb_float_new((double)$1[i][j])); 
+        }
+        rb_ary_push(ary, inner_ary);
+    }
+    $result = ary;
+}
+
+
+
+// Other stuff access
+
+/* playerc_rfidtag_t is an array of:
+typedef struct
+{
+    uint32_t type;
+    uint32_t guid_count;
+    uint8_t *guid;
+}  playerc_rfidtag_t;
+
+TODO: surely this is not the best interface to this data ever thought ...
+// Provide array access to the RFID tags
+// We will return an array of hashes. Each hash contains the RFID type, and 
the RFID ID.
+//  The RFID ID is a string containing the unprocessed bytes of the RFID tag.
+//  rfid.tags[i]["guid"].encode('hex') ?  to see the regular Hex-ASCII 
representation.
+*/
+%typemap(out) playerc_rfidtag_t [ANY]
+{
+  int i;
+  $result = rb_ary_new2($1_dim0);  //we will return an Array
+
+  //At this level, we dont get the ammount of tags, 
+  //so we just produce a long list, of size PLAYER_RFID_MAX_TAGS
+  //(this is the size of the array of playerc_rfidtag_t contained in the RFID 
data packet)
+  for (i = 0; i != $1_dim0; ++i)
+  {
+    VALUE hash = rb_hash_new();
+    
+    const unsigned int blength=PLAYERC_RFID_MAX_GUID;
+    char buffer[blength];
+    memset(buffer, 0, blength );
+
+    //result is of type playerc_rfidtag_t
+    unsigned int j;    
+    unsigned int guid_count=$1[i].guid_count;
+
+    //copy the bytes into the buffer
+    for (j=0 ; j != guid_count ; ++j) {
+       buffer[j]=$1[i].guid[j];
+    }
+
+    //generate a string from the buffer
+    VALUE guid = rb_str_new(buffer, guid_count);
+    //generate an Int from the tag type
+    VALUE type = UINT2NUM((long) (unsigned long long) $1[i].type);
+
+    //set the previous objects into the tuple
+    rb_hash_aset(hash, "type", type);
+    rb_hash_aset(hash, "guid", guid);
+
+    rb_ary_push ($result, hash);
+  }
+  //$result is the array that gets returned automatically at the end of this 
function
+}
+
+
+
+
+
+// Catch-all rule to converts arrays of structures to arrays of proxies for
+// the underlying structs 
+
+%typemap(out) SWIGTYPE [ANY]
+{
+  VALUE ary;
+  VALUE obj;
+  int i;
+  ary =rb_ary_new2($1_dim0);
+  for (i = 0; i < $1_dim0; i++)
+  {
+    obj = SWIG_NewPointerObj($1 + i, $1_descriptor, 0);
+    rb_ary_push(ary, obj);
+  }
+  $result = ary;
+}
+
+
+/******************************************
+
+     RUBY to C (Ruby writes)
+ $input Ruby types
+ $1 C types
+
+******************************************/
+
+
+
+%typemap(in) uint8_t
+{
+  $1 = NUM2CHR($input);
+}
+
+
+%typemap(in) uint16_t
+{
+  
+  $1 = (unsigned short) NUM2UINT($input);
+}
+
+
+%typemap(in) uint32_t
+{
+  
+  $1 = NUM2UINT($input);
+}
+
+
+
+
+
+// Provide array (write) access
+%typemap(in) double [ANY] (double temp[$1_dim0])
+{
+  //TODO check if the input is a correct Ruby array
+  //TODO: NUM2DBL and friends can return errors?
+  int i;
+  if (RARRAY_LEN($input) != $1_dim0) 
+  {
+    SWIG_exception( SWIG_TypeError, "Size mismatch on the array" );
+    return 0;
+  }
+
+  for (i = 0; i < $1_dim0; i++)
+  {
+    temp[i] = (double) NUM2DBL( rb_ary_entry($input, i) );
+  }
+  $1 = temp;
+}
+
+
+%typemap(in) float [ANY] (float temp[$1_dim0])
+{
+  //TODO check if the input is a correct Ruby array
+  int i;
+  if (RARRAY_LEN($input) != $1_dim0) 
+  {
+    SWIG_exception( SWIG_TypeError, "Size mismatch on the array" );
+    return 0;
+  }
+
+  for (i = 0; i < $1_dim0; i++)
+  {
+    temp[i] = (float) NUM2DBL( rb_ary_entry($input, i) );
+  }
+  $1 = temp;
+}
+
+
+
+%typemap(in) uint8_t data[]
+{
+//TODO check if the input is a correct Ruby array
+  int i;
+  int size;
+  
+  size = RARRAY_LEN($input);
+  $1 = (uint8_t*) malloc (size * sizeof (uint8_t));
+  
+  for (i = 0; i < size; i++)
+  {
+    $1[i] = (uint8_t) NUM2CHR( rb_ary_entry($input, i) );
+  }
+}
+
+
+
+/*// typemap to free the array created in the previous typemap
+%typemap(freearg) uint8_t data[]
+{
+  if ($input) free ((uint8_t*) $input);
+}*/
+
+/*
+// typemap for passing points into the graphics2d interface
+// in C is an array of structures, where each structure has two doubles: px 
and py
+// in Ruby an array of arrays is OK?
+%typemap(in) player_point_2d_t pts[]
+{
+//TODO: check we have a double array
+//check it has doubles
+  int i;
+  int size;
+  VALUE *structure;
+  
+  size = RARRAY_LEN($input);
+
+  $1 = (player_point_2d_t*) malloc (size * sizeof (player_point_2d_t));
+  for (i = 0; i < size; i++)
+  {
+    structure = rb_ary_entry($input, i);
+    $1[i][0] = (double) NUM2DBL( rb_ary_entry(structure, 0) );
+    $1[i][1] = (double) NUM2DBL( rb_ary_entry(structure, 1) );
+  }
+
+}
+
+*/
+
+
+
+
+// Include Player header so we can pick up some constants and generate
+// wrapper code for structs
+%include "libplayercore/player.h"
+%include "libplayercore/player_interfaces.h"
+
+//TODO: service discovering, needs wrapping
+//%include "libplayersd/playersd.h"
+
+
+
+// Use this for object-oriented bindings;
+// e.g., client.connect(...)
+// This file is created by running ../parse_header.py
+%include "playerc_wrap.i"
+

Added: 
code/player/trunk/client_libs/libplayerc/bindings/ruby/playerc_swig_parse.py
===================================================================
--- 
code/player/trunk/client_libs/libplayerc/bindings/ruby/playerc_swig_parse.py    
                            (rev 0)
+++ 
code/player/trunk/client_libs/libplayerc/bindings/ruby/playerc_swig_parse.py    
    2009-05-14 03:14:25 UTC (rev 7655)
@@ -0,0 +1,251 @@
+#!/usr/bin/env python
+
+import re
+import string
+import sys
+
+# Global array of PlayerStruct objects (defined below) to hold information 
about
+# structure definitions.
+structures=[]
+
+# Accessor functions to allow access to dynamic arrays (e.g. 
playerc_laser_t.ranges).
+# accessor_header goes in playerc_wrap.h, accessor_interface goes in 
playerc_wrap.i.
+accessor_header="""
+typedef struct
+{
+    TYPE *actual;
+} TYPEArray;
+"""
+
+accessor_interface="""
+typedef struct
+{
+    TYPE *actual;
+
+    %extend {
+        TYPE __getitem__(int index) {return $self->actual[index];}
+        void __setitem__(int index,TYPE value) {$self->actual[index]=value;}
+    }
+} TYPEArray;
+"""
+
+# Class for holding information about a detected structure, including a header
+# section for preprocessor directives and typedefs and a 'members' section for
+# external functions that become members.
+class PlayerStruct:
+    name=''
+    header=""
+    members=""
+    
+    def __init__(self,initName):
+        self.name=initName
+        
+    def __eq__(self,other):
+        if isinstance(other,str):
+            return self.name==other
+        return NotImplemented
+
+# Called for every function that matches the regex in main.  If successful,
+# the function will be removed, temporarily stored in a 'PlayerStruct' class,
+# and later reconstituted as a member function.
+def memberize(match):
+    # Used to remove the first parameter from a list of function parameters.
+    # The first parameter to a potential member function is a pointer to the 
structure
+    # to work with, which is not necessary after the transformation.
+    lastParams=re.compile('\(\s*\w+?.*?,\s*(?P<last>.*)\)',re.DOTALL)
+    funcName=match.group('name')
+    # The start of the loop checks chunks of the function name for a 
recognizable structure
+    # name.  e.g. playerc_some_class_do_some_action will try playerc_some, 
playerc_some_class
+    # and so on until a match is found.
+    objName="playerc"
+    for i in range(1,funcName.count("_")):
+        objName=funcName[:funcName.find("_",len(objName)+1)]
+        action=funcName[len(objName)+1:]
+        # Once a match is found, transform the external function to a member 
function.
+        if objName in structures:
+            struct=structures[structures.index(objName)]
+            # e.g. playerc_client_create
+            if action=="create":
+                # add the function to a structure
+                struct.members+="\t\t" + objName + " " + match.group('params') 
+ ";\n"
+                # add a preprocessor directive to ensure swig picks up the old 
library
+                # function name as a constructor.
+                struct.header+="\t#define new_" + objName + " " + funcName + 
"\n"
+            # e.g. playerc_client_destroy
+            elif action == "destroy":
+                # add the destructor to the structure.  No destructors take 
parameters
+                # or return a value.
+                struct.members+="\t\tvoid destroy(void);\n"
+                struct.header+="\t#define del_" + objName + " " + funcName + 
"\n"
+            # e.g. playerc_client_connect
+            else:
+                # set 'last' to every parameter in the parameter list except 
the first.
+                # if no match, there are less than two parameters, in which 
case the
+                # transformed function will have no parameters (void).
+                lm=lastParams.match(match.group('params'))
+                if lm:
+                    last=lm.group('last')
+                else:
+                    last="void"
+                # add the function prototype to the structure.
+                struct.members+="\t\t" + match.group('retval') + " " + action 
+ " (%s);\n" % last
+                # functions that are not constructors or destructors already 
match the required SWIG pattern,
+                # so no preprocessor directive is required.
+            # Since the function is a member function and will now have a 
prototype
+            # inside an 'extend' clause in the structure definition, remove 
the external
+            # reference by substituting with ''
+            return ''
+    # If the function is not a member function of a structure, take no action.
+    return match.group()
+
+# This function is called for every structure.  It attempts to find dynamically
+# allocated arrays of simple types (which are not subscriptable in python with
+# standard binding) and wrap them in an accessor structure defined at the top 
of this file.
+def accessorize(match):
+    # 'text' is the new code for the matched structure (to be returned)
+    text=match.group('decl')+"{"
+    # 'body' is everything within the {}s of the structure definition
+    body=match.group('body');
+    # 'arrayMember' is a regex designed to match certain member definitions,
+    # e.g. 'double *ranges;' (playerc_laser_t)
+    
arrayMember=re.compile(r"\b(?P<type>int|double|float)\s*[*]\s*(?P<name>\w+);",re.MULTILINE)
+    
+    # performs a substitution on the member definitions described above,
+    # e.g. 'double *ranges;' becomes 'doubleArray ranges;',
+    # and appends the modified struct body to the code.
+    text+=arrayMember.sub("\g<type>Array \g<name>;",body)
+    
+    # terminate the modified structure and add the 'footer', usually just the 
end
+    # of the typedef.
+    text+="}"+match.group('footer')
+    return text;
+
+# Called for every structure in the input stream.  Modifies the code block to 
include
+# an appropriate 'header' section with typedefs and preprocessor directives,
+# and adds new member function prototypes in a SWIG 'extend' block at the end 
of the
+# structure.
+def genifacestruct(match):
+    # ensure the structure has previously been scanned (should always be the 
case)
+    if match.group('name') in structures:
+        # retrieve the data about the matched structure
+        struct=structures[structures.index(match.group('name'))]
+        # add the header block and a typedef to permit the change from 
structname_t to structname
+        # (for clarity in python)
+        text="%header\n%{\n"+struct.header+"\ttypedef " + struct.name+"_t 
"+struct.name+";\n%}\n\n"
+        # add the structure declaration and the body, omitting a closing brace
+        text+=match.group('decl')+"{"+match.group('body')
+        # add the extension block with member function protoypes, plus a 
closing brace.
+        text+="\t%extend\n\t{\n"+struct.members+"\t}\n}"
+        # add the remainder of the original structure definition (usually just 
the typedef name)
+        text+=match.group('footer')
+        return text
+    # if no match, print a statement to that effect and return the original 
structure definition.
+    # should never happen.
+    print "No match on %s" % match.group('name')
+    return match.group() 
+
+# Used to remove _t from structure references.
+# Had to do this due to ambiguity with typedef statements and callback 
function prototypes.
+# e.g.   typedef void (*playerc_putmsg_fn_t) (void *device, char *header, char 
*data);
+# also   typedef player_blobfinder_blob_t playerc_blobfinder_blob_t;
+# This function ensures that only structures defined in playerc.h are modified.
+def underscore(match):
+    if match.group('name') in structures:
+        return match.group('name')
+    return match.group()
+
+if __name__ == '__main__':
+
+    # should always be playerc.h
+    infilename = sys.argv[1]
+    # should always be 'playerc_wrap'
+    outfilename = sys.argv[2]
+
+    # Read in the entire file
+    file = open(infilename, 'r')
+    ifaceStream = file.read()
+    file.close()
+
+    # Pattern to remove all double-spacing (used later)
+    blank=re.compile('([ \t\f\v\r]*\n){3,}',re.MULTILINE)
+
+    # Remove all comments (multi- and single-line).
+    comment=re.compile('((/\*.*?\*/)|(//.*?$))', re.DOTALL|re.MULTILINE)
+    ifaceStream=comment.sub('',ifaceStream)
+
+    # Pattern to recognise structure definitions
+    struct=re.compile("""
+        (?P<decl>typedef\s+struct\s*\w*\s*)  # Declaration
+        {(?P<body>.*?)}(?P<footer>\s*        # Body
+        (?P<name>playerc_\w+?)(_t)?          # Name
+        \s*;)
+    """, re.DOTALL|re.VERBOSE)
+    
+    # Match and replace all structure definitions with versions that have
+    # accessor structures for dynamically allocated arrays using the 
'accessorize'
+    # function above.
+    ifaceStream=struct.sub(accessorize,ifaceStream)
+    
+    # remove all double-spacing (pattern defined above)
+    ifaceStream=blank.sub('\n\n',ifaceStream)
+
+    # output to new header file.  It is necessary to modify the original 
header file to
+    # allow for data types of structure members to be changed.  Pointers are 
modified
+    # to structures containing a pointer, to allow the member to be 
subscriptable in python.
+    # see comments on the 'accessorize' function above.  
+    file=open("%s.h" % outfilename,"w")
+    # write accessor structure definitions for arrays of ints, doubles and 
floats.
+    for type in ["int","double","float"]:
+        file.write(accessor_header.replace("TYPE",type))
+    # write the modified header file.
+    file.write(ifaceStream)
+    file.close()
+    
+    # find the names of all the structures defined in the file, and make
+    # a list of objects to store information about the structures.
+    # could be done as part of 'accessorize' but left here for clarity.
+    am=struct.finditer(ifaceStream)
+    for m in am:
+        structures+=[PlayerStruct(m.group('name'))]
+
+    # Pattern to match function prototypes that could be changed to 'member 
functions'
+    # of structures, allowing object-oriented style calling from Python.
+    function=re.compile("""
+        \s*    
+        ((?P<retval>                  # Capture the return type:
+            \w+\s*?(                  # Type name, is a 
+            \** |                     # pointer OR
+            &?  |                     # reference OR
+            (\[\s*[0-9]*\s*\])        # array.
+            )
+        )\s*)?                        # Only one (potential) return value.
+        (?P<name>                     # Capture function name
+            playerc_\w+               # Class name and member function name
+        )\s*
+        (?P<params>\(.*?\))           # Parameters
+        \s*;
+    """, re.DOTALL|re.VERBOSE)
+
+    # remove the _t from the end of all the struct references.
+    structNames=re.compile(r"\b(?P<name>playerc_\w+)_t\b")
+    ifaceStream=structNames.sub(underscore,ifaceStream)
+
+    # using the 'memberize' function, find functions that should be struct 
'members' and shift them.
+    ifaceStream=function.sub(memberize,ifaceStream)
+
+    # Using the gathered information about functions and structures, rewrite 
the structure
+    # definitions in the interface file to include required extensions 
(function prototypes), 
+    # typedefs and preprocessor directives.  see comments on 'genifacestruct' 
function above.
+    ifaceStream=struct.sub(genifacestruct,ifaceStream)
+
+    # remove all double spacing.
+    ifaceStream=blank.sub('\n\n',ifaceStream)
+    
+    # write the SWIG interface definition file.
+    file=open("%s.i" % outfilename,"w")
+    # write interfaces for the accessor structs including subscripting 
functions.
+    for type in ["int","double","float"]:
+        file.write(accessor_interface.replace("TYPE",type))
+    file.write(ifaceStream)
+    file.close()
+    
\ No newline at end of file


Property changes on: 
code/player/trunk/client_libs/libplayerc/bindings/ruby/playerc_swig_parse.py
___________________________________________________________________
Added: svn:executable
   + *


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
The NEW KODAK i700 Series Scanners deliver under ANY circumstances! Your
production scanning environment may not be a perfect world - but thanks to
Kodak, there's a perfect scanner to get the job done! With the NEW KODAK i700
Series Scanner you'll get full speed at 300 dpi even with all image 
processing features enabled. http://p.sf.net/sfu/kodak-com
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit

Reply via email to