/* ----------------------------------------------------------------------------- * 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 #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(ANYARGS) { 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", swig_ruby_trackings_count, 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) { if (TYPE(object) != T_DATA) abort(); DATA_PTR(object) = 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(void* ptr, VALUE obj, void(*meth)(void* ptr, VALUE obj)) { (*meth)(ptr, obj); return ST_CONTINUE; } SWIGRUNTIME void SWIG_RubyIterateTrackings( void(*meth)(void* ptr, VALUE obj) ) { st_foreach(swig_ruby_trackings, (int (*)(ANYARGS))&swig_ruby_internal_iterate_callback, (st_data_t)meth); } #ifdef __cplusplus } #endif