/tags/rel-1-3-27/SWIG/Lib/ruby/rubytracking.swg
Unknown | 115 lines | 95 code | 20 blank | 0 comment | 0 complexity | 3b0af61e82d193ba5e88fa00ac9b2d96 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
1/***********************************************************************
2 * rubytracking.swg
3 *
4 * This file contains support for tracking mappings from
5 * Ruby objects to C++ objects. This functionality is needed
6 * to implement mark functions for Ruby's mark and sweep
7 * garbage collector.
8 ************************************************************************/
9
10/* Global Ruby hash table to store Trackings from C/C++
11 structs to Ruby Objects. */
12static VALUE swig_ruby_trackings;
13
14/* Setup a Ruby hash table to store Trackings */
15static void SWIG_RubyInitializeTrackings() {
16 /* Create a ruby hash table to store Trackings from C++
17 objects to Ruby objects. Also make sure to tell
18 the garabage collector about the hash table. */
19 swig_ruby_trackings = rb_hash_new();
20 rb_gc_register_address(&swig_ruby_trackings);
21}
22
23/* Get a Ruby number to reference a pointer */
24static VALUE SWIG_RubyPtrToReference(void* ptr) {
25 /* We cast the pointer to an unsigned long
26 and then store a reference to it using
27 a Ruby number object. */
28
29 /* Convert the pointer to a Ruby number */
30 unsigned long value = (unsigned long) ptr;
31 return LONG2NUM(value);
32}
33
34/* Get a Ruby number to reference an object */
35static VALUE SWIG_RubyObjectToReference(VALUE object) {
36 /* We cast the object to an unsigned long
37 and then store a reference to it using
38 a Ruby number object. */
39
40 /* Convert the Object to a Ruby number */
41 unsigned long value = (unsigned long) object;
42 return LONG2NUM(value);
43}
44
45/* Get a Ruby object from a previously stored reference */
46static VALUE SWIG_RubyReferenceToObject(VALUE reference) {
47 /* The provided Ruby number object is a reference
48 to the Ruby object we want.*/
49
50 /* First convert the Ruby number to a C number */
51 unsigned long value = NUM2LONG(reference);
52 return (VALUE) value;
53}
54
55/* Add a Tracking from a C/C++ struct to a Ruby object */
56static void SWIG_RubyAddTracking(void* ptr, VALUE object) {
57 /* In a Ruby hash table we store the pointer and
58 the associated Ruby object. The trick here is
59 that we cannot store the Ruby object directly - if
60 we do then it cannot be garbage collected. So
61 instead we typecast it as a unsigned long and
62 convert it to a Ruby number object.*/
63
64 /* Get a reference to the pointer as a Ruby number */
65 VALUE key = SWIG_RubyPtrToReference(ptr);
66
67 /* Get a reference to the Ruby object as a Ruby number */
68 VALUE value = SWIG_RubyObjectToReference(object);
69
70 /* Store the mapping to the global hash table. */
71 rb_hash_aset(swig_ruby_trackings, key, value);
72}
73
74/* Get the Ruby object that owns the specified C/C++ struct */
75static VALUE SWIG_RubyInstanceFor(void* ptr) {
76 /* Get a reference to the pointer as a Ruby number */
77 VALUE key = SWIG_RubyPtrToReference(ptr);
78
79 /* Now lookup the value stored in the global hash table */
80 VALUE value = rb_hash_aref(swig_ruby_trackings, key);
81
82 if (value == Qnil) {
83 /* No object exists - return nil. */
84 return Qnil;
85 }
86 else {
87 /* Convert this value to Ruby object */
88 return SWIG_RubyReferenceToObject(value);
89 }
90}
91
92/* Remove a Tracking from a C/C++ struct to a Ruby object */
93static void SWIG_RubyRemoveTracking(void* ptr) {
94 /* Get a reference to the pointer as a Ruby number */
95 VALUE key = SWIG_RubyPtrToReference(ptr);
96
97 /* Define delete method - in C++ this could be marked as
98 static but unfortunately not in C. */
99 VALUE delete_function = rb_intern("delete");
100
101 /* Delete the object from the hash table by calling Ruby's
102 do this we need to call the Hash.delete method.*/
103 rb_funcall(swig_ruby_trackings, delete_function, 1, key);
104}
105
106/* This is a helper method that unlinks a Ruby object from its
107 underlying C++ object. This is needed if the lifetime of the
108 Ruby object is longer than the C++ object */
109static void SWIG_RubyUnlinkObjects(void* ptr) {
110 VALUE object = SWIG_RubyInstanceFor(ptr);
111
112 if (object != Qnil) {
113 DATA_PTR(object) = 0;
114 }
115}