registry.cc
Go to the documentation of this file.
00001 #include "typelib.hh"
00002 
00003 #include <typelib/pluginmanager.hh>
00004 #include <typelib/importer.hh>
00005 #include <typelib/exporter.hh>
00006 #include <typelib/registryiterator.hh>
00007 #include <lang/csupport/standard_types.hh>
00008 #include <utilmm/configfile/configset.hh>
00009 #include <set>
00010 
00011 using namespace Typelib;
00012 using utilmm::config_set;
00013 using namespace std;
00014 using namespace typelib_ruby;
00015 using cxx2rb::RbRegistry;
00016 
00017 
00018 namespace typelib_ruby {
00019     VALUE cRegistry = Qnil;
00020     VALUE eNotFound = Qnil;
00021 }
00022 
00023 /***********************************************************************************
00024  *
00025  * Wrapping of the Registry class
00026  *
00027  */
00028 
00029 
00030 static 
00031 void registry_free(void* ptr)
00032 {
00033     using cxx2rb::WrapperMap;
00034     RbRegistry* rbregistry = reinterpret_cast<RbRegistry*>(ptr);
00035     WrapperMap& wrappers = rbregistry->wrappers;
00036     for (WrapperMap::iterator it = wrappers.begin(); it != wrappers.end(); ++it)
00037     {
00038         if (it->second.first)
00039             delete it->first;
00040     }
00041 
00042     delete rbregistry;
00043 }
00044 
00045 static
00046 void registry_mark(void* ptr)
00047 {
00048     using cxx2rb::WrapperMap;
00049     WrapperMap const& wrappers = reinterpret_cast<RbRegistry const*>(ptr)->wrappers;
00050     for (WrapperMap::const_iterator it = wrappers.begin(); it != wrappers.end(); ++it)
00051         rb_gc_mark(it->second.second);
00052 }
00053 
00054 static
00055 VALUE registry_wrap(VALUE klass, Registry* registry)
00056 {
00057     return Data_Wrap_Struct(klass, registry_mark, registry_free, new RbRegistry(registry));
00058 }
00059 
00060 static
00061 VALUE registry_alloc(VALUE klass)
00062 {
00063     Registry* registry = new Registry;
00064     return registry_wrap(klass, registry);
00065 }
00066 
00067 
00068 static
00069 VALUE registry_includes_p(VALUE self, VALUE name)
00070 {
00071     Registry& registry = rb2cxx::object<Registry>(self);
00072     Type const* type = registry.get( StringValuePtr(name) );
00073     return type ? Qtrue : Qfalse;
00074 }
00075 
00076 /* call-seq:
00077  *   registry.remove(type) => removed_types
00078  *
00079  * Removes +type+ from the registry, along with all the types that depends on
00080  * +type+.
00081  *
00082  * Returns the set of removed types
00083  */
00084 static
00085 VALUE registry_remove(VALUE self, VALUE rbtype)
00086 {
00087     RbRegistry& rbregistry = rb2cxx::object<RbRegistry>(self);
00088     Registry&   registry = *(rbregistry.registry);
00089     Type const& type(rb2cxx::object<Type>(rbtype));
00090     std::set<Type*> deleted = registry.remove(type);
00091     
00092     VALUE result = rb_ary_new();
00093     std::set<Type*>::iterator it, end;
00094     for (it = deleted.begin(); it != deleted.end(); ++it)
00095     {
00096         rb_ary_push(result, cxx2rb::type_wrap(**it, self));
00097         cxx2rb::WrapperMap::iterator wrapper_it = rbregistry.wrappers.find(*it);
00098         wrapper_it->second.first = true;
00099     }
00100 
00101     return result;
00102 }
00103 
00104 /* call-seq:
00105  *   registry.source_id_of(type) => source_or_nil
00106  *
00107  * Returns the source ID for the given type, if one is set
00108  */
00109 static
00110 VALUE registry_source_id_of(VALUE self, VALUE rbtype)
00111 {
00112     RbRegistry& rbregistry = rb2cxx::object<RbRegistry>(self);
00113     Registry&   registry = *(rbregistry.registry);
00114     Type const& type(rb2cxx::object<Type>(rbtype));
00115 
00116     RegistryIterator it = registry.find(type.getName());
00117     if (it == registry.end())
00118         rb_raise(rb_eArgError, "this registry has no type called %s", type.getName().c_str());
00119 
00120     std::string source = it.getSource();
00121     if (source.empty()) return Qnil;
00122     return rb_str_new(it.getSource().c_str(), it.getSource().length());
00123 }
00124 
00125 /* call-seq:
00126  *   registry.reverse_depends(type) => types
00127  *
00128  * Returns the array of types that depend on +type+, including +type+ itself
00129  */
00130 static
00131 VALUE registry_reverse_depends(VALUE self, VALUE rbtype)
00132 {
00133     Registry const& registry = rb2cxx::object<Registry>(self);
00134     Type const& type(rb2cxx::object<Type>(rbtype));
00135     std::set<Type const*> rdeps = registry.reverseDepends(type);
00136     
00137     VALUE result = rb_ary_new();
00138     std::set<Type const*>::iterator it, end;
00139     for (it = rdeps.begin(); it != rdeps.end(); ++it)
00140         rb_ary_push(result, cxx2rb::type_wrap(**it, self));
00141 
00142     return result;
00143 }
00144 
00145 static
00146 VALUE registry_do_get(VALUE self, VALUE name)
00147 {
00148     Registry& registry = rb2cxx::object<Registry>(self);
00149     Type const* type = registry.get( StringValuePtr(name) );
00150 
00151     if (! type)
00152         rb_raise(eNotFound, "there is no type in this registry with the name '%s'", StringValuePtr(name));
00153     return cxx2rb::type_wrap(*type, self);
00154 }
00155 
00156 static
00157 VALUE registry_do_build(VALUE self, VALUE name)
00158 {
00159     Registry& registry = rb2cxx::object<Registry>(self);
00160     try {
00161         Type const* type = registry.build( StringValuePtr(name) );
00162         if (! type) 
00163             rb_raise(eNotFound, "cannot find %s in registry", StringValuePtr(name));
00164         return cxx2rb::type_wrap(*type, self);
00165     }
00166     catch(std::exception const& e) { rb_raise(rb_eRuntimeError, "%s", e.what()); }
00167 }
00168 
00169 
00170 /* call-seq:
00171  *  alias(new_name, name)           => self
00172  *
00173  * Make +new_name+ refer to the type named +name+
00174  */
00175 static
00176 VALUE registry_alias(VALUE self, VALUE name, VALUE aliased)
00177 {
00178     Registry& registry = rb2cxx::object<Registry>(self);
00179 
00180     try { 
00181         registry.alias(StringValuePtr(aliased), StringValuePtr(name)); 
00182         return self;
00183     } catch(BadName) {
00184         rb_raise(rb_eArgError, "invalid type name %s", StringValuePtr(name));
00185     } catch(Undefined) {
00186         rb_raise(eNotFound, "there is not type in this registry with the name '%s'", StringValuePtr(aliased));
00187     }
00188 }
00189 
00190 static
00191 void setup_configset_from_option_array(config_set& config, VALUE options)
00192 {
00193     int options_length = RARRAY_LEN(options);
00194     for (int i = 0; i < options_length; ++i)
00195     {
00196         VALUE entry = RARRAY_PTR(options)[i];
00197         VALUE k = RARRAY_PTR(entry)[0];
00198         VALUE v = RARRAY_PTR(entry)[1];
00199 
00200         if ( rb_obj_is_kind_of(v, rb_cArray) )
00201         {
00202             VALUE first_el = rb_ary_entry(v, 0);
00203             if (rb_obj_is_kind_of(first_el, rb_cArray))
00204             {
00205                 // We are building recursive config sets
00206                 for (int j = 0; j < RARRAY_LEN(v); ++j)
00207                 {
00208                     config_set* child = new config_set;
00209                     setup_configset_from_option_array(*child, rb_ary_entry(v, j));
00210                     config.insert(StringValuePtr(k), child);
00211                 }
00212             }
00213             else
00214             {
00215                 for (int j = 0; j < RARRAY_LEN(v); ++j)
00216                 {
00217                     VALUE value = rb_ary_entry(v, j);
00218                     config.insert(StringValuePtr(k), StringValuePtr(value));
00219                 }
00220             }
00221         }
00222         else if (TYPE(v) == T_TRUE || TYPE(v) == T_FALSE)
00223             config.set(StringValuePtr(k), RTEST(v) ? "true" : "false");
00224         else
00225             config.set(StringValuePtr(k), StringValuePtr(v));
00226     }
00227 }
00228 
00229 /* Private method to import a given file in the registry
00230  * We expect Registry#import to format the arguments before calling
00231  * do_import
00232  */
00233 static
00234 VALUE registry_import(VALUE self, VALUE file, VALUE kind, VALUE merge, VALUE options)
00235 {
00236     Registry& registry = rb2cxx::object<Registry>(self);
00237 
00238     config_set config;
00239     setup_configset_from_option_array(config, options);
00240     
00241     std::string error_string;
00242     try { 
00243         if (RTEST(merge))
00244         {
00245             Registry temp;
00246             PluginManager::load(StringValuePtr(kind), StringValuePtr(file), config, temp); 
00247             registry.merge(temp);
00248         }
00249         else
00250             PluginManager::load(StringValuePtr(kind), StringValuePtr(file), config, registry); 
00251         return Qnil;
00252     }
00253     catch(boost::bad_lexical_cast e)   { error_string = e.what(); }
00254     catch(std::exception const& e) { error_string = e.what(); }
00255 
00256     rb_raise(rb_eRuntimeError, "%s", error_string.c_str());
00257 }
00258 
00259 /* Private method called by Registry#export. This latter method is supposed
00260  * to format the +options+ argument from a Ruby hash into an array suitable
00261  * for setup_configset_from_option_array
00262  */
00263 static
00264 VALUE registry_export(VALUE self, VALUE kind, VALUE options)
00265 {
00266     Registry& registry = rb2cxx::object<Registry>(self);
00267 
00268     config_set config;
00269     setup_configset_from_option_array(config, options);
00270     
00271     string error_message;
00272     try {
00273         std::string exported = PluginManager::save(StringValuePtr(kind), config, registry);
00274         return rb_str_new(exported.c_str(), exported.length());
00275     }
00276     catch (std::exception const& e) { error_message = e.what(); }
00277     rb_raise(rb_eRuntimeError, "%s", error_message.c_str());
00278 }
00279 
00280 
00281 /*
00282  * call-seq:
00283  *   merge(other_registry) => self
00284  *
00285  * Move all types found in +other_registry+ into +self+
00286  */
00287 static
00288 VALUE registry_merge(VALUE self, VALUE rb_merged)
00289 {
00290     std::string error_string;
00291 
00292     Registry& registry = rb2cxx::object<Registry>(self);
00293     Registry& merged   = rb2cxx::object<Registry>(rb_merged);
00294     try { 
00295         registry.merge(merged);
00296         return self;
00297     }
00298     catch(std::exception const& e) { error_string = e.what(); }
00299     rb_raise(rb_eRuntimeError, "%s", error_string.c_str());
00300 }
00301 
00302 
00303 /*
00304  * call-seq:
00305  *   resize(new_sizes) => nil
00306  *
00307  * Changes the size of some types, while modifying the types that depend on
00308  * them to keep the registry consistent.
00309  */
00310 static
00311 VALUE registry_resize(VALUE self, VALUE new_sizes)
00312 {
00313     Registry& registry = rb2cxx::object<Registry>(self);
00314 
00315     std::map<std::string, size_t> sizes;
00316     size_t map_size   = RARRAY_LEN(new_sizes);
00317     VALUE* map_values = RARRAY_PTR(new_sizes);
00318     for (size_t i = 0; i < map_size; ++i)
00319     {
00320         VALUE* pair = RARRAY_PTR(map_values[i]);
00321         sizes.insert(std::make_pair(
00322                 StringValuePtr(pair[0]),
00323                 NUM2INT(pair[1])));
00324     }
00325     try { 
00326         registry.resize(sizes);
00327         return Qnil;
00328     }
00329     catch(std::exception const& e) {
00330         rb_raise(rb_eRuntimeError, "%s", e.what());
00331     }
00332 }
00333 
00334 /* call-seq:
00335  *  minimal(auto_types) => registry
00336  *
00337  * Returns the minimal registry needed to define all types that are in +self+
00338  * but not in +auto_types+
00339  */
00340 static
00341 VALUE registry_minimal(VALUE self, VALUE rb_auto, VALUE with_aliases)
00342 {
00343     std::string error_string;
00344     Registry& registry   = rb2cxx::object<Registry>(self);
00345 
00346     if (rb_obj_is_kind_of(rb_auto, rb_cString))
00347     {
00348         try { 
00349             Registry* result = registry.minimal(StringValuePtr(rb_auto), RTEST(with_aliases));
00350             return registry_wrap(cRegistry, result);
00351         }
00352         catch(std::exception const& e)
00353         { rb_raise(rb_eRuntimeError, "%s", e.what()); }
00354     }
00355     else
00356     {
00357         Registry& auto_types = rb2cxx::object<Registry>(rb_auto);
00358         try { 
00359             Registry* result = registry.minimal(auto_types);
00360             return registry_wrap(cRegistry, result);
00361         }
00362         catch(std::exception const& e)
00363         { rb_raise(rb_eRuntimeError, "%s", e.what()); }
00364     }
00365 }
00366 
00367 
00368 static void yield_types(VALUE self, bool with_aliases, RegistryIterator it, RegistryIterator end)
00369 {
00370     if (with_aliases)
00371     {
00372         for (; it != end; ++it)
00373         {
00374             std::string const& type_name = it.getName();
00375             VALUE rb_type_name = rb_str_new(type_name.c_str(), type_name.length());
00376             rb_yield_values(2, rb_type_name, cxx2rb::type_wrap(*it, self));
00377         }
00378     }
00379     else
00380     {
00381         for (; it != end; ++it)
00382         {
00383             if (!it.isAlias())
00384                 rb_yield(cxx2rb::type_wrap(*it, self));
00385         }
00386     }
00387 }
00388 
00389 /*
00390  * each_type(filter, false) { |type| ... }
00391  * each_type(filter, true)  { |name, type| ... }
00392  *
00393  * Iterates on the types found in this registry. If include_alias is true, also
00394  * yield the aliased types. If +filter+ is not nil, only the types whose names
00395  * start with +filter+ will be yield
00396  */
00397 static
00398 VALUE registry_each_type(VALUE self, VALUE filter_, VALUE with_aliases_)
00399 {
00400     Registry& registry = rb2cxx::object<Registry>(self);
00401     bool with_aliases = RTEST(with_aliases_);
00402     std::string filter;
00403     if (RTEST(filter_))
00404         filter = StringValuePtr(filter_);
00405 
00406     try 
00407     {
00408         if (filter.empty())
00409             yield_types(self, with_aliases, registry.begin(), registry.end());
00410         else
00411             yield_types(self, with_aliases, registry.begin(filter), registry.end(filter));
00412 
00413         return self;
00414     }
00415     catch(std::exception const& e)
00416     {
00417         rb_raise(rb_eRuntimeError, "%s", e.what());
00418     }
00419 }
00420 
00421 /* call-seq:
00422  *  registry.merge_xml(xml) => registry
00423  * 
00424  * Build a registry from a string, which is formatted as Typelib's own XML
00425  * format.  See also #export, #import and #to_xml
00426  */
00427 static
00428 VALUE registry_merge_xml(VALUE rb_registry, VALUE xml)
00429 {
00430     Registry& registry = rb2cxx::object<Registry>(rb_registry);
00431 
00432     std::istringstream istream(StringValuePtr(xml));
00433     config_set config;
00434     try { PluginManager::load("tlb", istream, config, registry); }
00435     catch(boost::bad_lexical_cast e)
00436     { rb_raise(rb_eArgError, "cannot load xml: %s", e.what()); }
00437     catch(std::exception const& e)
00438     { rb_raise(rb_eArgError, "cannot load xml: %s", e.what()); }
00439 
00440     return rb_registry;
00441 }
00442 
00443 /*
00444  * call-seq:
00445  *  Registry.aliases_of(type) => list_of_names
00446  *
00447  * Lists all the known aliases for the given type
00448  */
00449 static VALUE registry_aliases_of(VALUE self, VALUE type_)
00450 {
00451     Registry& registry = rb2cxx::object<Registry>(self);
00452     Type const& type(rb2cxx::object<Type>(type_));
00453     std::set<std::string> aliases =
00454         registry.getAliasesOf(type);
00455 
00456     VALUE result = rb_ary_new();
00457     for (set<string>::const_iterator it = aliases.begin(); it != aliases.end(); ++it)
00458         rb_ary_push(result, rb_str_new(it->c_str(), it->length()));
00459     return result;
00460 }
00461 
00462 /*
00463  * call-seq:
00464  *  registry.clear_aliases
00465  *
00466  * Removes all aliases defined on this registry
00467  */
00468 static VALUE registry_clear_aliases(VALUE self)
00469 {
00470     Registry& registry = rb2cxx::object<Registry>(self);
00471     registry.clearAliases();
00472     return Qnil;
00473 }
00474 
00475 /*
00476  * call-seq:
00477  *  registry.size => size
00478  *
00479  * Returns the number of types registered in +self+
00480  */
00481 static VALUE registry_size(VALUE self)
00482 {
00483     Registry& registry = rb2cxx::object<Registry>(self);
00484     return INT2NUM(registry.size());
00485 }
00486 
00487 /*
00488  * call-seq:
00489  *  Registry.available_containers => container_names
00490  *
00491  * Returns the set of known container names
00492  */
00493 static VALUE registry_available_container(VALUE registry_module)
00494 {
00495     Typelib::Container::AvailableContainers containers =
00496         Typelib::Container::availableContainers();
00497 
00498     VALUE result = rb_ary_new();
00499     Typelib::Container::AvailableContainers::const_iterator
00500         it = containers.begin(),
00501         end = containers.end();
00502 
00503     while (it != end)
00504     {
00505         std::string name = it->first;
00506         rb_ary_push(result, rb_str_new(name.c_str(), name.length()));
00507         ++it;
00508     }
00509     return result;
00510 }
00511 
00512 /*
00513  * call-seq:
00514  *  registry.define_container(kind, element_type) => new_type
00515  *
00516  * Defines a new container instance with the given container kind and element
00517  * type. +element_type+ is a type object, i.e. a subclass of Type, that has to
00518  * be part of +registry+ (obtained through registry.get or registry.build). If
00519  * +element_type+ comes from another registry object, the method raises
00520  * ArgumentError.
00521  *
00522  * Moreover, the method raises NotFound if +kind+ is not a known container name.
00523  */
00524 static VALUE registry_define_container(VALUE registry, VALUE kind, VALUE element)
00525 {
00526     Registry& reg = rb2cxx::object<Registry>(registry);
00527     Type const& element_type(rb2cxx::object<Type>(element));
00528     // Check that +reg+ contains +element_type+
00529     if (!reg.isIncluded(element_type))
00530         rb_raise(rb_eArgError, "the given type object comes from a different type registry");
00531 
00532     try {
00533         Container const& new_type = Container::createContainer(reg, StringValuePtr(kind), element_type);
00534         return cxx2rb::type_wrap(new_type, registry);
00535     } catch(Typelib::UnknownContainer) {
00536         rb_raise(eNotFound, "%s is not a known container type", StringValuePtr(kind));
00537     }
00538 }
00539 
00540 /*
00541  * call-seq:
00542  *  Registry.add_standard_cxx_types(registry) => registry
00543  *
00544  * Adds to +registry+  some standard C/C++ types that Typelib can represent
00545  */
00546 static VALUE registry_add_standard_cxx_types(VALUE klass, VALUE registry)
00547 {
00548     Registry& reg = rb2cxx::object<Registry>(registry);
00549     Typelib::CXX::addStandardTypes(reg);
00550     return registry;
00551 }
00552 
00553 /*
00554  * call-seq:
00555  *   registry.create_compound(name, field_defs)
00556  *
00557  * Creates a new compound type in which the fields are provided by +field_defs+
00558  */
00559 static VALUE registry_create_compound(VALUE registry, VALUE name, VALUE field_defs)
00560 {
00561     Registry& reg = rb2cxx::object<Registry>(registry);
00562 
00563     std::auto_ptr<Typelib::Compound> new_t(new Typelib::Compound(StringValuePtr(name)));
00564 
00565     int size = RARRAY_LEN(field_defs);
00566     for (int i = 0; i < size; ++i)
00567     {
00568         VALUE field = rb_ary_entry(field_defs, i);
00569 
00570         VALUE rb_name = rb_ary_entry(field, 0);
00571         std::string field_name(StringValuePtr(rb_name));
00572         Typelib::Type& field_type(rb2cxx::object<Type>(rb_ary_entry(field, 1)));
00573         int offset(NUM2INT(rb_ary_entry(field, 2)));
00574         new_t->addField(field_name, field_type, offset);
00575     }
00576 
00577     Typelib::Compound* type = new_t.release();
00578     try { reg.add(type, true, ""); }
00579     catch(std::runtime_error e)
00580     { rb_raise(rb_eArgError, "%s", e.what()); }
00581     return cxx2rb::type_wrap(*type, registry);
00582 }
00583 
00584 /*
00585  * call-seq:
00586  *   registry.create_enum(name, symbol_defs)
00587  *
00588  * Creates a new compound type in which the fields are provided by +field_defs+
00589  */
00590 static VALUE registry_create_enum(VALUE registry, VALUE name, VALUE symbol_defs)
00591 {
00592     Registry& reg = rb2cxx::object<Registry>(registry);
00593 
00594     std::auto_ptr<Typelib::Enum> new_t(new Typelib::Enum(StringValuePtr(name)));
00595 
00596     int size = RARRAY_LEN(symbol_defs);
00597     for (int i = 0; i < size; ++i)
00598     {
00599         VALUE sym = rb_ary_entry(symbol_defs, i);
00600 
00601         VALUE rb_name = rb_ary_entry(sym, 0);
00602         std::string sym_name(StringValuePtr(rb_name));
00603         int sym_value(NUM2INT(rb_ary_entry(sym, 1)));
00604         new_t->add(sym_name, sym_value);
00605     }
00606 
00607     Typelib::Enum* type = new_t.release();
00608     try { reg.add(type, true, ""); }
00609     catch(std::runtime_error e)
00610     { rb_raise(rb_eArgError, "%s", e.what()); }
00611     return cxx2rb::type_wrap(*type, registry);
00612 }
00613 
00614 void typelib_ruby::Typelib_init_registry()
00615 {
00616     VALUE mTypelib  = rb_define_module("Typelib");
00617     cRegistry = rb_define_class_under(mTypelib, "Registry", rb_cObject);
00618     eNotFound = rb_define_class_under(mTypelib, "NotFound", rb_eRuntimeError);
00619     rb_define_alloc_func(cRegistry, registry_alloc);
00620     rb_define_method(cRegistry, "size", RUBY_METHOD_FUNC(registry_size), 0);
00621     rb_define_method(cRegistry, "get", RUBY_METHOD_FUNC(registry_do_get), 1);
00622     rb_define_method(cRegistry, "build", RUBY_METHOD_FUNC(registry_do_build), 1);
00623     rb_define_method(cRegistry, "each_type", RUBY_METHOD_FUNC(registry_each_type), 2);
00624     // do_import is called by the Ruby-defined import, which formats the 
00625     // option hash (if there is one), and can detect the import type by extension
00626     rb_define_method(cRegistry, "do_import", RUBY_METHOD_FUNC(registry_import), 4);
00627     rb_define_method(cRegistry, "do_export", RUBY_METHOD_FUNC(registry_export), 2);
00628     rb_define_method(cRegistry, "merge_xml", RUBY_METHOD_FUNC(registry_merge_xml), 1);
00629     rb_define_method(cRegistry, "alias", RUBY_METHOD_FUNC(registry_alias), 2);
00630     rb_define_method(cRegistry, "clear_aliases", RUBY_METHOD_FUNC(registry_clear_aliases), 0);
00631     rb_define_method(cRegistry, "aliases_of", RUBY_METHOD_FUNC(registry_aliases_of), 1);
00632     rb_define_method(cRegistry, "merge", RUBY_METHOD_FUNC(registry_merge), 1);
00633     rb_define_method(cRegistry, "do_minimal", RUBY_METHOD_FUNC(registry_minimal), 2);
00634     rb_define_method(cRegistry, "includes?", RUBY_METHOD_FUNC(registry_includes_p), 1);
00635     rb_define_method(cRegistry, "do_resize", RUBY_METHOD_FUNC(registry_resize), 1);
00636     rb_define_method(cRegistry, "reverse_depends", RUBY_METHOD_FUNC(registry_reverse_depends), 1);
00637     rb_define_method(cRegistry, "remove", RUBY_METHOD_FUNC(registry_remove), 1);
00638     rb_define_method(cRegistry, "source_id_of", RUBY_METHOD_FUNC(registry_source_id_of), 1);
00639     rb_define_method(cRegistry, "do_create_compound", RUBY_METHOD_FUNC(registry_create_compound), 2);
00640     rb_define_method(cRegistry, "do_create_enum", RUBY_METHOD_FUNC(registry_create_enum), 2);
00641 
00642     rb_define_singleton_method(cRegistry, "add_standard_cxx_types", RUBY_METHOD_FUNC(registry_add_standard_cxx_types), 1);
00643 
00644     rb_define_singleton_method(cRegistry, "available_containers", RUBY_METHOD_FUNC(registry_available_container), 0);
00645     rb_define_method(cRegistry, "define_container", RUBY_METHOD_FUNC(registry_define_container), 2);
00646 }
00647 


typelib
Author(s): Sylvain Joyeux/sylvain.joyeux@m4x.org
autogenerated on Thu Jan 2 2014 11:38:41