| /* ----------------------------------------------------------------------------- | |
| * rubytracking.swg | |
| * | |
| * This file contains support for tracking mappings from | |
| * Ruby objects to C++ objects. This functionality is needed | |
| * to implement mark functions for Ruby's mark and sweep | |
| * garbage collector. | |
| * ----------------------------------------------------------------------------- */ | |
| #ifdef __cplusplus | |
| extern "C" { | |
| #endif | |
| #if !defined(ST_DATA_T_DEFINED) | |
| /* Needs to be explicitly included for Ruby 1.8 and earlier */ | |
| #include <st.h> | |
| #endif | |
| /* Ruby 1.8 actually assumes the first case. */ | |
| #if SIZEOF_VOIDP == SIZEOF_LONG | |
| # define SWIG2NUM(v) LONG2NUM((unsigned long)v) | |
| # define NUM2SWIG(x) (unsigned long)NUM2LONG(x) | |
| #elif SIZEOF_VOIDP == SIZEOF_LONG_LONG | |
| # define SWIG2NUM(v) LL2NUM((unsigned long long)v) | |
| # define NUM2SWIG(x) (unsigned long long)NUM2LL(x) | |
| #else | |
| # error sizeof(void*) is not the same as long or long long | |
| #endif | |
| /* Global hash table to store Trackings from C/C++ | |
| structs to Ruby Objects. | |
| */ | |
| static st_table* swig_ruby_trackings = NULL; | |
| static VALUE swig_ruby_trackings_count(ID id, VALUE *var) { | |
| return SWIG2NUM(swig_ruby_trackings->num_entries); | |
| } | |
| /* Setup a hash table to store Trackings */ | |
| SWIGRUNTIME void SWIG_RubyInitializeTrackings(void) { | |
| /* Create a hash table to store Trackings from C++ | |
| objects to Ruby objects. */ | |
| /* Try to see if some other .so has already created a | |
| tracking hash table, which we keep hidden in an instance var | |
| in the SWIG module. | |
| This is done to allow multiple DSOs to share the same | |
| tracking table. | |
| */ | |
| VALUE trackings_value = Qnil; | |
| /* change the variable name so that we can mix modules | |
| compiled with older SWIG's - this used to be called "@__trackings__" */ | |
| ID trackings_id = rb_intern( "@__safetrackings__" ); | |
| VALUE verbose = rb_gv_get("VERBOSE"); | |
| rb_gv_set("VERBOSE", Qfalse); | |
| trackings_value = rb_ivar_get( _mSWIG, trackings_id ); | |
| rb_gv_set("VERBOSE", verbose); | |
| /* The trick here is that we have to store the hash table | |
| pointer in a Ruby variable. We do not want Ruby's GC to | |
| treat this pointer as a Ruby object, so we convert it to | |
| a Ruby numeric value. */ | |
| if (trackings_value == Qnil) { | |
| /* No, it hasn't. Create one ourselves */ | |
| swig_ruby_trackings = st_init_numtable(); | |
| rb_ivar_set( _mSWIG, trackings_id, SWIG2NUM(swig_ruby_trackings) ); | |
| } else { | |
| swig_ruby_trackings = (st_table*)NUM2SWIG(trackings_value); | |
| } | |
| rb_define_virtual_variable("SWIG_TRACKINGS_COUNT", | |
| VALUEFUNC(swig_ruby_trackings_count), | |
| SWIG_RUBY_VOID_ANYARGS_FUNC((rb_gvar_setter_t*)NULL)); | |
| } | |
| /* Add a Tracking from a C/C++ struct to a Ruby object */ | |
| SWIGRUNTIME void SWIG_RubyAddTracking(void* ptr, VALUE object) { | |
| /* Store the mapping to the global hash table. */ | |
| st_insert(swig_ruby_trackings, (st_data_t)ptr, object); | |
| } | |
| /* Get the Ruby object that owns the specified C/C++ struct */ | |
| SWIGRUNTIME VALUE SWIG_RubyInstanceFor(void* ptr) { | |
| /* Now lookup the value stored in the global hash table */ | |
| VALUE value; | |
| if (st_lookup(swig_ruby_trackings, (st_data_t)ptr, &value)) { | |
| return value; | |
| } else { | |
| return Qnil; | |
| } | |
| } | |
| /* Remove a Tracking from a C/C++ struct to a Ruby object. It | |
| is very important to remove objects once they are destroyed | |
| since the same memory address may be reused later to create | |
| a new object. */ | |
| SWIGRUNTIME void SWIG_RubyRemoveTracking(void* ptr) { | |
| /* Delete the object from the hash table */ | |
| st_delete(swig_ruby_trackings, (st_data_t *)&ptr, NULL); | |
| } | |
| /* This is a helper method that unlinks a Ruby object from its | |
| underlying C++ object. This is needed if the lifetime of the | |
| Ruby object is longer than the C++ object. */ | |
| SWIGRUNTIME void SWIG_RubyUnlinkObjects(void* ptr) { | |
| VALUE object = SWIG_RubyInstanceFor(ptr); | |
| if (object != Qnil) { | |
| // object might have the T_ZOMBIE type, but that's just | |
| // because the GC has flagged it as such for a deferred | |
| // destruction. Until then, it's still a T_DATA object. | |
| struct swig_ruby_wrapped_object *wrobj = (struct swig_ruby_wrapped_object *)RTYPEDDATA_GET_DATA(object); | |
| if (wrobj) | |
| wrobj->data = 0; | |
| } | |
| } | |
| /* This is a helper method that iterates over all the trackings | |
| passing the C++ object pointer and its related Ruby object | |
| to the passed callback function. */ | |
| /* Proxy method to abstract the internal trackings datatype */ | |
| static int swig_ruby_internal_iterate_callback(st_data_t ptr, st_data_t obj, st_data_t meth) { | |
| ((void (*) (void *, VALUE))meth)((void *)ptr, (VALUE)obj); | |
| return ST_CONTINUE; | |
| } | |
| SWIGRUNTIME void SWIG_RubyIterateTrackings( void(*meth)(void* ptr, VALUE obj) ) { | |
| st_foreach(swig_ruby_trackings, | |
| SWIG_RUBY_INT_ANYARGS_FUNC(swig_ruby_internal_iterate_callback), | |
| (st_data_t)meth); | |
| } | |
| #ifdef __cplusplus | |
| } | |
| #endif |