$search
00001 #include "typelib.hh" 00002 #include <iostream> 00003 00004 #include <boost/bind.hpp> 00005 #include <typelib/value_ops.hh> 00006 00007 using namespace Typelib; 00008 using std::vector; 00009 using namespace typelib_ruby; 00010 00011 /********************************************** 00012 * Typelib::Compound 00013 */ 00014 00015 static VALUE compound_get_fields(VALUE self) 00016 { 00017 if (self == cCompound) 00018 return rb_ary_new(); 00019 00020 Type const& type(rb2cxx::object<Type>(self)); 00021 Compound const& compound(dynamic_cast<Compound const&>(type)); 00022 Compound::FieldList const& fields(compound.getFields()); 00023 Compound::FieldList::const_iterator it, end = fields.end(); 00024 00025 VALUE registry = type_get_registry(self); 00026 VALUE fieldlist = rb_ary_new(); 00027 for (it = fields.begin(); it != end; ++it) 00028 { 00029 VALUE field_name = rb_str_new2(it->getName().c_str()); 00030 VALUE field_type = cxx2rb::type_wrap(it->getType(), registry); 00031 00032 VALUE field_def = rb_ary_new2(3); 00033 rb_ary_store(field_def, 0, field_name); 00034 rb_ary_store(field_def, 1, INT2FIX(it->getOffset())); 00035 rb_ary_store(field_def, 2, field_type); 00036 rb_ary_push(fieldlist, field_def); 00037 } 00038 00039 return fieldlist; 00040 } 00041 00042 /* Helper function for CompoundType#[] */ 00043 static VALUE compound_field_get(VALUE rbvalue, VALUE name) 00044 { 00045 VALUE registry = value_get_registry(rbvalue); 00046 Value value = rb2cxx::object<Value>(rbvalue); 00047 if (! value.getData()) 00048 return Qnil; 00049 00050 try { 00051 Value field_value = value_get_field(value, StringValuePtr(name)); 00052 return typelib_to_ruby(field_value, registry, rbvalue); 00053 } 00054 catch(FieldNotFound) 00055 { rb_raise(rb_eArgError, "no field '%s'", StringValuePtr(name)); } 00056 catch(std::exception const& e) 00057 { rb_raise(rb_eRuntimeError, "%s", e.what()); } 00058 } 00059 /* Helper function for CompoundType#[]= */ 00060 static VALUE compound_field_set(VALUE self, VALUE name, VALUE newval) 00061 { 00062 Value& tlib_value(rb2cxx::object<Value>(self)); 00063 00064 try { 00065 Value field_value = value_get_field(tlib_value, StringValuePtr(name)); 00066 typelib_from_ruby(field_value, newval); 00067 return newval; 00068 } 00069 catch(FieldNotFound) 00070 { rb_raise(rb_eArgError, "no field '%s' in '%s'", StringValuePtr(name), rb_obj_classname(self)); } 00071 catch(std::exception const& e) 00072 { rb_raise(rb_eRuntimeError, "%s", e.what()); } 00073 } 00074 00075 /* call-seq: 00076 * pointer.deference => pointed-to type 00077 * 00078 * Returns the value pointed to by +self+ 00079 */ 00080 static VALUE pointer_deference(VALUE self) 00081 { 00082 VALUE pointed_to = rb_iv_get(self, "@points_to"); 00083 if (!NIL_P(pointed_to)) 00084 return pointed_to; 00085 00086 Value const& value(rb2cxx::object<Value>(self)); 00087 Indirect const& indirect(static_cast<Indirect const&>(value.getType())); 00088 00089 VALUE registry = value_get_registry(self); 00090 00091 void* ptr_value = *reinterpret_cast<void**>(value.getData()); 00092 if (!ptr_value) 00093 rb_raise(rb_eArgError, "cannot deference a NULL pointer"); 00094 00095 Value new_value(ptr_value, indirect.getIndirection() ); 00096 return typelib_to_ruby(new_value, registry, Qnil); 00097 } 00098 00099 00100 /* Get the C value associated with a ruby representation of an enum 00101 * Valid ruby representations are: symbols, strings and integer 00102 */ 00103 Enum::integral_type rb2cxx::enum_value(VALUE rb_value, Enum const& e) 00104 { 00105 // m_value can be either an integer, a symbol or a string 00106 if (TYPE(rb_value) == T_FIXNUM) 00107 { 00108 Enum::integral_type value = FIX2INT(rb_value); 00109 try { 00110 e.get(value); 00111 return value; 00112 } 00113 catch(Enum::ValueNotFound) { } 00114 rb_raise(rb_eArgError, "%i is not a valid value for %s", value, e.getName().c_str()); 00115 } 00116 00117 char const* name; 00118 if (SYMBOL_P(rb_value)) 00119 name = rb_id2name(SYM2ID(rb_value)); 00120 else 00121 name = StringValuePtr(rb_value); 00122 00123 try { return e.get(name); } 00124 catch(Enum::SymbolNotFound) { } 00125 rb_raise(rb_eArgError, "%s is not a valid symbol for %s", name, e.getName().c_str()); 00126 } 00127 00128 /* call-seq: 00129 * enum.keys => array of keys 00130 * 00131 * Returns a string array of all the keys defined for this enumeration 00132 */ 00133 VALUE enum_keys(VALUE self) 00134 { 00135 Enum const& type = static_cast<Enum const&>(rb2cxx::object<Type>(self)); 00136 00137 VALUE keys = rb_iv_get(self, "@values"); 00138 if (!NIL_P(keys)) 00139 return keys; 00140 00141 keys = rb_hash_new(); 00142 typedef std::list<std::string> string_list; 00143 string_list names = type.names(); 00144 for (string_list::const_iterator it = names.begin(); it != names.end(); ++it) 00145 rb_hash_aset(keys, rb_str_new2(it->c_str()), INT2FIX(type.get(*it))); 00146 00147 rb_iv_set(self, "@values", keys); 00148 return keys; 00149 } 00150 00151 /* call-seq: 00152 * enum.value_of(name) => integer 00153 * 00154 * Returns the integral value asoociated with the given name. 00155 */ 00156 static VALUE enum_value_of(VALUE self, VALUE name) 00157 { 00158 Enum const& type = static_cast<Enum const&>(rb2cxx::object<Type>(self)); 00159 00160 try { 00161 int value = type.get(StringValuePtr(name)); 00162 return INT2NUM(value); 00163 } catch (Enum::SymbolNotFound) { 00164 rb_raise(rb_eArgError, "this enumeration has no value for %s", StringValuePtr(name)); 00165 } 00166 } 00167 00168 /* call-seq: 00169 * enum.name_of(integer) => key 00170 * 00171 * Returns the symbolic name of +integer+ in this enumeration, or raises 00172 * ArgumentError if there is no matching name. 00173 */ 00174 static VALUE enum_name_of(VALUE self, VALUE integer) 00175 { 00176 Enum const& type = static_cast<Enum const&>(rb2cxx::object<Type>(self)); 00177 00178 try { 00179 std::string name = type.get(NUM2INT(integer)); 00180 return rb_str_new2(name.c_str()); 00181 } catch (Enum::ValueNotFound) { 00182 rb_raise(rb_eArgError, "this enumeration has no name for %i", NUM2INT(integer)); 00183 } 00184 } 00185 00186 /********************************************** 00187 * Typelib::Pointer 00188 */ 00189 00190 /* call-seq: 00191 * type.deference => other_type 00192 * 00193 * Returns the type referenced by this one 00194 */ 00195 static VALUE indirect_type_deference(VALUE self) 00196 { 00197 VALUE registry = type_get_registry(self); 00198 Type const& type(rb2cxx::object<Type>(self)); 00199 Indirect const& indirect(static_cast<Indirect const&>(type)); 00200 return cxx2rb::type_wrap(indirect.getIndirection(), registry); 00201 } 00202 00203 00204 static Value array_element(VALUE rbarray, VALUE rbindex) 00205 { 00206 Value& value(rb2cxx::object<Value>(rbarray)); 00207 Array const& array(static_cast<Array const&>(value.getType())); 00208 size_t index = NUM2INT(rbindex); 00209 00210 if (index >= array.getDimension()) 00211 { 00212 rb_raise(rb_eIndexError, "Out of bounds: %lu > %lu", index, array.getDimension()); 00213 return Value(); 00214 } 00215 00216 Type const& array_type(array.getIndirection()); 00217 00218 int8_t* data = reinterpret_cast<int8_t*>(value.getData()); 00219 data += array_type.getSize() * index; 00220 return Value(data, array_type); 00221 } 00222 00223 /* call-seq: 00224 * array[index] => value 00225 * 00226 * Returns the value at +index+ in the array. Since Typelib arrays are *not* 00227 * dynamically extensible, trying to set a non-existent index will raise an 00228 * IndexError exception. 00229 */ 00230 static VALUE array_get(int argc, VALUE* argv, VALUE self) 00231 { 00232 Value& value = rb2cxx::object<Value>(self); 00233 Array const& array = static_cast<Array const&>(value.getType()); 00234 if (array.getDimension() == 0) 00235 return self; 00236 00237 Type const& array_type = array.getIndirection(); 00238 VALUE registry = value_get_registry(self); 00239 00240 int8_t* data = reinterpret_cast<int8_t*>(value.getData()); 00241 size_t index = NUM2INT(argv[0]); 00242 if (index >= array.getDimension()) 00243 rb_raise(rb_eIndexError, "Out of bounds: %li > %li", index, array.getDimension()); 00244 00245 if (argc == 1) 00246 { 00247 Value v = Value(data + array_type.getSize() * index, array_type); 00248 return typelib_to_ruby( v, registry, self ); 00249 } 00250 else if (argc == 2) 00251 { 00252 VALUE ret = rb_ary_new(); 00253 size_t size = NUM2INT(argv[1]); 00254 if (index + size > array.getDimension()) 00255 rb_raise(rb_eIndexError, "Out of bounds: %li > %li", index + size - 1, array.getDimension()); 00256 00257 for (size_t i = index; i < index + size; ++i) 00258 { 00259 Value v = Value(data + array_type.getSize() * i, array_type); 00260 VALUE rb_v = typelib_to_ruby( v, registry, self ); 00261 00262 rb_ary_push(ret, rb_v); 00263 } 00264 00265 return ret; 00266 } 00267 else 00268 rb_raise(rb_eArgError, "invalid argument count (%i for 1 or 2)", argc); 00269 } 00270 00271 /* call-seq: 00272 * array[index] = new_value => new_value 00273 * 00274 * Sets the value at +index+ to +new_value+. Since Typelib arrays are *not* 00275 * dynamically extensible, trying to set a non-existent index will raise an 00276 * IndexError exception. 00277 */ 00278 static VALUE array_set(VALUE self, VALUE rbindex, VALUE newvalue) 00279 { 00280 Value element = array_element(self, rbindex); 00281 return typelib_from_ruby(element, newvalue); 00282 } 00283 00284 /* call-seq: 00285 * array.each { |v| ... } => array 00286 * 00287 * Iterates on all elements of the array 00288 */ 00289 static VALUE array_do_each(VALUE rbarray) 00290 { 00291 Value& value = rb2cxx::object<Value>(rbarray); 00292 Array const& array = static_cast<Array const&>(value.getType()); 00293 if (array.getDimension() == 0) 00294 return rbarray; 00295 00296 Type const& array_type = array.getIndirection(); 00297 VALUE registry = value_get_registry(rbarray); 00298 00299 int8_t* data = reinterpret_cast<int8_t*>(value.getData()); 00300 00301 for (size_t i = 0; i < array.getDimension(); ++i, data += array_type.getSize()) 00302 rb_yield(typelib_to_ruby( Value(data, array_type), registry, rbarray )); 00303 00304 return rbarray; 00305 } 00306 00307 /* call-seq: 00308 * array.size => size 00309 * 00310 * Returns the count of elements in +array+ 00311 */ 00312 static VALUE array_size(VALUE rbarray) 00313 { 00314 Value& value(rb2cxx::object<Value>(rbarray)); 00315 Array const& array(static_cast<Array const&>(value.getType())); 00316 return INT2FIX(array.getDimension()); 00317 } 00318 00319 /* call-seq: 00320 * array.length => length 00321 * 00322 * Returns the count of elemnts in +array+ 00323 */ 00324 static VALUE array_class_length(VALUE rbarray) 00325 { 00326 Array const& array(dynamic_cast<Array const&>(rb2cxx::object<Type>(rbarray))); 00327 return INT2FIX(array.getDimension()); 00328 } 00329 00330 /* 00331 * call-seq: 00332 * pointer.null? => boolean 00333 * 00334 * checks if this is a NULL pointer 00335 */ 00336 static VALUE pointer_nil_p(VALUE self) 00337 { 00338 Value const& value(rb2cxx::object<Value>(self)); 00339 if ( *reinterpret_cast<void**>(value.getData()) == 0 ) 00340 return Qtrue; 00341 return Qfalse; 00342 } 00343 00344 /* 00345 * call-seq: 00346 * numeric.integer? => true or false 00347 * 00348 * Returns true if the type is an integral type and false if it is a floating-point type 00349 */ 00350 static VALUE numeric_type_integer_p(VALUE self) 00351 { 00352 Numeric const& type(dynamic_cast<Numeric const&>(rb2cxx::object<Type>(self))); 00353 return type.getNumericCategory() == Numeric::Float ? Qfalse : Qtrue; 00354 } 00355 00356 /* 00357 * call-seq: 00358 * numeric.size => value 00359 * 00360 * The size of this type in bytes 00361 */ 00362 static VALUE numeric_type_size(VALUE self) 00363 { 00364 Numeric const& type(dynamic_cast<Numeric const&>(rb2cxx::object<Type>(self))); 00365 return INT2FIX(type.getSize()); 00366 } 00367 00368 /* 00369 * call-seq: 00370 * numeric.unsigned? => value 00371 * 00372 * If integer? returns true, returns whether this type is an unsigned or signed 00373 * integral type. 00374 */ 00375 static VALUE numeric_type_unsigned_p(VALUE self) 00376 { 00377 Numeric const& type(dynamic_cast<Numeric const&>(rb2cxx::object<Type>(self))); 00378 switch(type.getNumericCategory()) 00379 { 00380 case Numeric::SInt: return Qfalse; 00381 case Numeric::UInt: return Qtrue; 00382 case Numeric::Float: 00383 rb_raise(rb_eArgError, "not an integral type"); 00384 } 00385 return Qnil; // never reached 00386 } 00387 00388 00389 /* 00390 * call-seq: 00391 * klass.container_kind => name 00392 * 00393 * Returns the name of the generic container. For instance, a 00394 * /std/vector</double> type would return /std/vector. 00395 */ 00396 static VALUE container_kind(VALUE self) 00397 { 00398 Container const& type(dynamic_cast<Container const&>(rb2cxx::object<Type>(self))); 00399 return rb_str_new2(type.kind().c_str()); 00400 } 00401 00402 /* 00403 * call-seq: 00404 * container.natural_size => a_number 00405 * 00406 * Returns the container's size on the local machine. This can be different from 00407 * the value returned by size() in case a registry has been generated on a 00408 * different architecture. 00409 */ 00410 static VALUE container_natural_size(VALUE self) 00411 { 00412 Container const& type(dynamic_cast<Container const&>(rb2cxx::object<Type>(self))); 00413 return INT2FIX(type.getNaturalSize()); 00414 } 00415 00416 /* 00417 * call-seq: 00418 * container.random_access? 00419 * 00420 * Returns true if this container type is a random access container 00421 */ 00422 static VALUE container_random_access_p(VALUE self) 00423 { 00424 Container const& type(dynamic_cast<Container const&>(rb2cxx::object<Type>(self))); 00425 return type.isRandomAccess() ? Qtrue : Qfalse; 00426 } 00427 00428 00429 /* 00430 * call-seq: 00431 * container.length => value 00432 * 00433 * Returns the count of elements in +container+ 00434 */ 00435 static VALUE container_length(VALUE self) 00436 { 00437 Value value = rb2cxx::object<Value>(self); 00438 Container const& type(dynamic_cast<Container const&>(value.getType())); 00439 00440 return INT2NUM(type.getElementCount(value.getData())); 00441 } 00442 00443 /* 00444 * call-seq: 00445 * container.clear 00446 * 00447 * Removes all elements from that container 00448 */ 00449 static VALUE container_clear(VALUE self) 00450 { 00451 Value value = rb2cxx::object<Value>(self); 00452 Container const& type(dynamic_cast<Container const&>(value.getType())); 00453 00454 type.clear(value.getData()); 00455 return Qnil; 00456 } 00457 00458 static Typelib::Value container_element(uint64_t* buffer10, Type const& element_t, VALUE obj) 00459 { 00460 Typelib::Value element_v; 00461 if (element_t.getCategory() == Type::Numeric && sizeof(int64_t) * 10 >= element_t.getSize()) 00462 { 00463 // Special case: allow the caller to use Ruby numeric directly. This is 00464 // way faster if a lot of insertions need to be done 00465 element_v = Value(buffer10, element_t); 00466 typelib_from_ruby(element_v, obj); 00467 } 00468 else 00469 { 00470 element_v = rb2cxx::object<Value>(obj); 00471 if (element_t != element_v.getType()) 00472 rb_raise(rb_eArgError, "wrong type %s for new element, expected %s", element_v.getType().getName().c_str(), element_t.getName().c_str()); 00473 } 00474 return element_v; 00475 } 00476 00477 static VALUE container_do_push(VALUE self, VALUE obj) 00478 { 00479 Value container_v = rb2cxx::object<Value>(self); 00480 Container const& container_t(dynamic_cast<Container const&>(container_v.getType())); 00481 00482 uint64_t buffer[10]; 00483 Value element_v = container_element(buffer, container_t.getIndirection(), obj); 00484 container_t.push(container_v.getData(), element_v); 00485 return self; 00486 } 00487 00488 static VALUE container_do_set(VALUE self, VALUE index, VALUE obj) 00489 { 00490 Value container_v = rb2cxx::object<Value>(self); 00491 Container const& container_t(dynamic_cast<Container const&>(container_v.getType())); 00492 00493 uint64_t buffer[10]; 00494 Value element_v = container_element(buffer, container_t.getIndirection(), obj); 00495 container_t.setElement(container_v.getData(), NUM2INT(index), element_v); 00496 return self; 00497 } 00498 00499 static VALUE container_do_get(VALUE self, VALUE index) 00500 { 00501 Value container_v = rb2cxx::object<Value>(self); 00502 Container const& container_t(dynamic_cast<Container const&>(container_v.getType())); 00503 VALUE registry = value_get_registry(self); 00504 00505 Value v = container_t.getElement(container_v.getData(), NUM2INT(index)); 00506 return typelib_to_ruby(v, registry, self); 00507 } 00508 00509 struct ContainerIterator : public RubyGetter 00510 { 00511 bool inside; 00512 00513 bool visit_(Value const& v, Container const& c) 00514 { 00515 if (inside) 00516 RubyGetter::visit_(v, c); 00517 else 00518 ValueVisitor::visit_(v, c); 00519 return false; 00520 } 00521 00522 void apply(Value v, VALUE registry, VALUE parent) 00523 { 00524 inside = false; 00525 RubyGetter::apply(v, registry, parent); 00526 } 00527 virtual void dispatch(Value v) 00528 { 00529 inside = true; 00530 RubyGetter::dispatch(v); 00531 00532 VALUE result = m_value; 00533 m_value = Qnil; 00534 rb_yield(result); 00535 } 00536 }; 00537 00538 /* 00539 * call-seq: 00540 * container.each { |obj| ... } => container 00541 * 00542 * Iterates on the elements of the container 00543 */ 00544 static VALUE container_each(VALUE self) 00545 { 00546 Value value = rb2cxx::object<Value>(self); 00547 VALUE registry = value_get_registry(self); 00548 ContainerIterator iterator; 00549 iterator.apply(value, registry, self); 00550 return self; 00551 } 00552 00553 /* 00554 * call-seq: 00555 * container.erase(obj) => true or false 00556 * 00557 * Removes +obj+ from the container. Returns true if +obj+ has been found and 00558 * deleted, and false otherwise 00559 */ 00560 static VALUE container_erase(VALUE self, VALUE obj) 00561 { 00562 Value container_v = rb2cxx::object<Value>(self); 00563 Container const& container_t(dynamic_cast<Container const&>(container_v.getType())); 00564 00565 uint64_t buffer[10]; 00566 Value element_v = container_element(buffer, container_t.getIndirection(), obj); 00567 00568 if (container_t.erase(container_v.getData(), element_v)) 00569 return Qtrue; 00570 else 00571 return Qfalse; 00572 } 00573 00574 bool container_delete_if_i(Value v, VALUE registry, VALUE container) 00575 { 00576 VALUE rb_v = typelib_to_ruby(v, registry, container); 00577 if (RTEST(rb_yield(rb_v))) 00578 return true; 00579 return false; 00580 } 00581 00582 /* 00583 * call-seq: 00584 * container.delete_if { |obj| ... } => container 00585 * 00586 * Removes the elements in the container for which the block returns true. 00587 */ 00588 static VALUE container_delete_if(VALUE self) 00589 { 00590 Value container_v = rb2cxx::object<Value>(self); 00591 Container const& container_t(dynamic_cast<Container const&>(container_v.getType())); 00592 00593 VALUE registry = value_get_registry(self); 00594 container_t.delete_if(container_v.getData(), boost::bind(container_delete_if_i, _1, registry, self)); 00595 return self; 00596 } 00597 00598 /* 00599 * call-seq: 00600 * value.to_ruby => non-Typelib object or self 00601 * 00602 * Converts +self+ to its Ruby equivalent. If no equivalent 00603 * type is available, returns self 00604 */ 00605 static VALUE numeric_to_ruby(VALUE self) 00606 { 00607 Value const& value(rb2cxx::object<Value>(self)); 00608 VALUE registry = value_get_registry(self); 00609 try { 00610 return typelib_to_ruby(value, registry, Qnil); 00611 } catch(Typelib::NullTypeFound) { } 00612 rb_raise(rb_eTypeError, "trying to convert 'void'"); 00613 } 00614 00615 /* 00616 * call-seq: 00617 * value.from_ruby(ruby_object) => self 00618 * 00619 * Initializes +self+ with the information contained in +ruby_object+. 00620 * 00621 * This particular method is not type-safe. You should use Typelib.from_ruby 00622 * unless you know what you are doing. 00623 */ 00624 static VALUE numeric_from_ruby(VALUE self, VALUE arg) 00625 { 00626 Value& value(rb2cxx::object<Value>(self)); 00627 try { 00628 typelib_from_ruby(value, arg); 00629 return self; 00630 } catch(Typelib::UnsupportedType) { } 00631 rb_raise(rb_eTypeError, "cannot perform the requested convertion"); 00632 } 00633 00634 00635 /* Document-class: Typelib::NumericType 00636 * 00637 * Wrapper for numeric types (int, float, ...) 00638 */ 00639 00640 /* Document-class: Typelib::IndirectType 00641 * 00642 * Base class for types which deference other objects, like pointers or arrays 00643 * See also ArrayType and PointerType 00644 */ 00645 00646 /* Document-class: Typelib::PointerType 00647 * 00648 * Base class for pointers (references to other values) 00649 */ 00650 00651 /* Document-class: Typelib::CompoundType 00652 * 00653 * Base class for types composed by other types (structures and unions in C). 00654 * Each field is assigned its type and its offset inside the structure. So 00655 * unions are represented with all fields having an offset of zero, while 00656 * structures have consecutive offsets. 00657 */ 00658 00659 void typelib_ruby::Typelib_init_specialized_types() 00660 { 00661 VALUE mTypelib = rb_define_module("Typelib"); 00662 cNumeric = rb_define_class_under(mTypelib, "NumericType", cType); 00663 rb_define_singleton_method(cNumeric, "integer?", RUBY_METHOD_FUNC(numeric_type_integer_p), 0); 00664 rb_define_singleton_method(cNumeric, "unsigned?", RUBY_METHOD_FUNC(numeric_type_unsigned_p), 0); 00665 rb_define_singleton_method(cNumeric, "size", RUBY_METHOD_FUNC(numeric_type_size), 0); 00666 rb_define_method(cNumeric, "typelib_to_ruby", RUBY_METHOD_FUNC(&numeric_to_ruby), 0); 00667 rb_define_method(cNumeric, "typelib_from_ruby", RUBY_METHOD_FUNC(&numeric_from_ruby), 1); 00668 00669 cOpaque = rb_define_class_under(mTypelib, "OpaqueType", cType); 00670 cNull = rb_define_class_under(mTypelib, "NullType", cType); 00671 00672 cIndirect = rb_define_class_under(mTypelib, "IndirectType", cType); 00673 rb_define_singleton_method(cIndirect, "deference", RUBY_METHOD_FUNC(indirect_type_deference), 0); 00674 00675 cPointer = rb_define_class_under(mTypelib, "PointerType", cIndirect); 00676 rb_define_method(cPointer, "deference", RUBY_METHOD_FUNC(pointer_deference), 0); 00677 rb_define_method(cPointer, "null?", RUBY_METHOD_FUNC(pointer_nil_p), 0); 00678 00679 cCompound = rb_define_class_under(mTypelib, "CompoundType", cType); 00680 rb_define_singleton_method(cCompound, "get_fields", RUBY_METHOD_FUNC(compound_get_fields), 0); 00681 rb_define_method(cCompound, "typelib_get_field", RUBY_METHOD_FUNC(compound_field_get), 1); 00682 rb_define_method(cCompound, "typelib_set_field", RUBY_METHOD_FUNC(compound_field_set), 2); 00683 00684 cEnum = rb_define_class_under(mTypelib, "EnumType", cType); 00685 rb_define_singleton_method(cEnum, "keys", RUBY_METHOD_FUNC(enum_keys), 0); 00686 rb_define_singleton_method(cEnum, "value_of", RUBY_METHOD_FUNC(enum_value_of), 1); 00687 rb_define_singleton_method(cEnum, "name_of", RUBY_METHOD_FUNC(enum_name_of), 1); 00688 rb_define_method(cEnum, "typelib_to_ruby", RUBY_METHOD_FUNC(&numeric_to_ruby), 0); 00689 rb_define_method(cEnum, "typelib_from_ruby", RUBY_METHOD_FUNC(&numeric_from_ruby), 1); 00690 00691 cArray = rb_define_class_under(mTypelib, "ArrayType", cIndirect); 00692 rb_define_singleton_method(cArray, "length", RUBY_METHOD_FUNC(array_class_length), 0); 00693 rb_define_method(cArray, "do_get", RUBY_METHOD_FUNC(array_get), -1); 00694 rb_define_method(cArray, "do_set", RUBY_METHOD_FUNC(array_set), 2); 00695 rb_define_method(cArray, "do_each", RUBY_METHOD_FUNC(array_do_each), 0); 00696 rb_define_method(cArray, "size", RUBY_METHOD_FUNC(array_size), 0); 00697 00698 cContainer = rb_define_class_under(mTypelib, "ContainerType", cIndirect); 00699 rb_define_singleton_method(cContainer, "container_kind", RUBY_METHOD_FUNC(container_kind), 0); 00700 rb_define_singleton_method(cContainer, "natural_size", RUBY_METHOD_FUNC(container_natural_size), 0); 00701 rb_define_singleton_method(cContainer, "random_access?", RUBY_METHOD_FUNC(container_random_access_p), 0); 00702 rb_define_method(cContainer, "length", RUBY_METHOD_FUNC(container_length), 0); 00703 rb_define_method(cContainer, "size", RUBY_METHOD_FUNC(container_length), 0); 00704 rb_define_method(cContainer, "do_clear", RUBY_METHOD_FUNC(container_clear), 0); 00705 rb_define_method(cContainer, "do_push", RUBY_METHOD_FUNC(container_do_push), 1); 00706 rb_define_method(cContainer, "do_get", RUBY_METHOD_FUNC(container_do_get), 1); 00707 rb_define_method(cContainer, "do_set", RUBY_METHOD_FUNC(container_do_set), 2); 00708 rb_define_method(cContainer, "do_each", RUBY_METHOD_FUNC(container_each), 0); 00709 rb_define_method(cContainer, "do_erase", RUBY_METHOD_FUNC(container_erase), 1); 00710 rb_define_method(cContainer, "do_delete_if", RUBY_METHOD_FUNC(container_delete_if), 0); 00711 } 00712