Skip to content
Snippets Groups Projects
FXRuby.cpp 63.6 KiB
Newer Older
/***********************************************************************
 * FXRuby -- the Ruby language bindings for the FOX GUI toolkit.
 * Copyright (c) 2001-2003 by J. Lyle Johnson. All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * For further information please contact the author by e-mail
 * at "lyle@users.sourceforge.net".
 ***********************************************************************/

/***********************************************************************
 * $Id: FXRuby.cpp 2933 2008-12-29 20:19:33Z lyle $
 ***********************************************************************/

#ifdef _MSC_VER
#pragma warning (disable : 4786)
#endif

#include "FXRbCommon.h"

#include "version.h"

#if RUBY_VERSION_CODE < 167
#define RB_RESCUE2_BROKEN_PROTOTYPE 1
#endif

// The prototype for st_foreach() changed at Ruby version 1.8.2
#if RUBY_VERSION_CODE < 182
#define ST_BROKEN_PROTOTYPES 1
#endif

#include "impl.h"

#ifdef __CYGWIN__
#include <io.h>		// for get_osf_handle()
#endif

#ifdef HAVE_SIGNAL_H
#include <signal.h>	// for definitions of SIGINT, etc.
#endif

extern "C" {
#include "rubyio.h"	// for GetOpenFile(), etc.
}
#else
#include "ruby/io.h"
#endif

// Symbol table functions from Ruby. If we included "st.h" directly
// we'd be dealing with broken prototypes anyways, so just duplicate
// the needed declarations here with the correct prototypes.

#if defined(ST_BROKEN_PROTOTYPES)

extern "C" {

struct st_table;

typedef char * st_data_t; /* this type changed to unsigned long at Ruby 1.8.2 */

st_table *st_init_strtable();
st_table *st_init_numtable();
int st_lookup(st_table *table, st_data_t key, st_data_t *value);
int st_insert(st_table *table, st_data_t key, st_data_t value);
int st_delete(st_table *table, st_data_t *key, st_data_t *value);
void st_foreach(st_table *table, int (*func)(st_data_t, st_data_t, st_data_t), st_data_t arg);

}

#else

#ifdef RUBY_1_9

#include "ruby/st.h"

#else

extern "C" {
#include "st.h"
}

#endif /* RUBY_1_9 */

#endif /* ST_BROKEN_PROTOTYPES */

// Opaque type declaration from SWIG runtime
struct swig_type_info;

// Wrapper around SWIG_TypeQuery() that caches results for performance
swig_type_info *FXRbTypeQuery(const char *desc){
  FXASSERT(desc!=0);
  static st_table *types=st_init_strtable();
  swig_type_info *typeinfo=0;
  if(st_lookup(types,reinterpret_cast<st_data_t>(const_cast<char*>(desc)),reinterpret_cast<st_data_t *>(&typeinfo))==0){
    typeinfo=SWIG_Ruby_TypeQuery(desc);
    st_insert(types,reinterpret_cast<st_data_t>(strdup(desc)),reinterpret_cast<st_data_t>(typeinfo));
    }
  FXASSERT(typeinfo!=0);
  return typeinfo;
  }


/**
 * The FXRuby_Objects hash table basically maps C++ objects to Ruby instances.
 * Each key in the table is a pointer to a C++ object we've seen before, and
 * the corresponding value is an FXRubyObjDesc struct (see below) that tells
 * us which Ruby instance corresponds to that C++ object.
 */

static st_table * FXRuby_Objects;

/**
 * Each value in the FXRuby_Objects hash table is an instance of this
 * struct. It identifies the Ruby instance associated with a C++ object.
 * It also indicates whether this is merely a "borrowed" reference to
 * some C++ object (i.e. it's not one we need to destroy later).
 */

struct FXRubyObjDesc {
  VALUE obj;
  bool borrowed;
  };


/**
 * FXRbNewPointerObj() is a wrapper around SWIG_Ruby_NewPointerObj() that also
 * registers this C++ object & Ruby instance pair in our FXRuby_Objects
 * hash table. This function should only get called for methods that return
 * a reference to an already-existing C++ object (i.e. one that FOX "owns")
 * and for that reason we mark these objects as "borrowed".
 */

VALUE FXRbNewPointerObj(void *ptr,swig_type_info* ty){
  if(ptr!=0){
    FXASSERT(ty!=0);
    VALUE obj;
    FXRubyObjDesc *desc;
    if(FXMALLOC(&desc,FXRubyObjDesc,1)){
      obj=SWIG_Ruby_NewPointerObj(ptr,ty,1);
      desc->obj=obj;
      desc->borrowed=true;
      st_insert(FXRuby_Objects,reinterpret_cast<st_data_t>(ptr),reinterpret_cast<st_data_t>(desc));
      return obj;
      }
    else{
      FXASSERT(FALSE);
      return Qnil;
      }
    }
  else{
    return Qnil;
    }
  }


/**
 * FXRbIsBorrowed() returns true if the specified C++ object is one that
 * FOX owns (i.e. it's borrowed).
 */

bool FXRbIsBorrowed(void* ptr){
  FXASSERT(ptr!=0);
  FXRubyObjDesc *desc;
  if(st_lookup(FXRuby_Objects,reinterpret_cast<st_data_t>(ptr),reinterpret_cast<st_data_t *>(&desc))!=0){
    return desc->borrowed;
    }
  else{
    return true;
    }
  }


/**
 * FXRbConvertPtr() is just a wrapper around SWIG_Ruby_ConvertPtr().
 */

void* FXRbConvertPtr(VALUE obj,swig_type_info* ty){
  void *ptr;
  SWIG_Ruby_ConvertPtr(obj,&ptr,ty,1);
  return ptr;
  }


// Should we catch exceptions thrown by message handlers?
FXbool FXRbCatchExceptions=FALSE;
Loading
Loading full blame...