Hi,

At Thu, 8 Aug 2002 06:01:35 +0900,
GOTO Kentaro wrote:
> > test.rb:3:in `require': identifier Proto::ProtoStruct needs to be constant (NameError) from 
> > test.rb:3
> 
> > void Init_proto()
> > {
> >    VALUE np_mNet;
> >    np_mNet = rb_define_module("Net");
> >    cNetProto = rb_define_class_under(np_mNet,"Proto",rb_cObject);
> > 
> >    sProto = rb_struct_define("Proto::ProtoStruct","name","aliases","number",0);
> >   rb_global_variable(&sProto);
> 
> try replacing the last two lines by
> 
>   sProto = rb_struct_define("ProtoStruct","name","aliases","number",0);
>   rb_define_const(cNetProto, "ProtoStruct", sProto);

This pollute Struct namespace, to avoid it:
  * rb_struct_define() with NULL for first argument,
  * rb_define_const() like above, and
  * name the Struct with rb_set_class_path().

BTW, how about this, singleton methods "[]" which accepts
protocol name/number and "each" alias of "getprotent", and
extening Net::Proto with Enumerable.

require "net/proto"

p Net::Proto["tcp"], Net::Proto[6]
Net::Proto.each {|proto| p proto}
p Net::Proto.to_a



#include "ruby.h" #include <netdb.h> #include <string.h> #define BUF_SIZE 8192 static VALUE np_getprotobyname(VALUE obj, VALUE proto_name) { struct protoent p, *r; char buffer[BUF_SIZE]; getprotobyname_r(StringValuePtr(proto_name), &p, buffer, BUF_SIZE, &r); return INT2NUM(p.p_proto); } static VALUE np_getprotobynumber(VALUE obj, VALUE proto_number) { struct protoent p, *r; char buffer[BUF_SIZE]; getprotobynumber_r(NUM2INT(proto_number), &p, buffer, BUF_SIZE, &r); return rb_str_new2(p.p_name); } static VALUE np_aref(VALUE obj, VALUE proto) { if (TYPE(proto) == T_STRING) { return np_getprotobyname(obj, proto); } else { return np_getprotobynumber(obj, proto); } } static VALUE np_getprotoent(VALUE self) { struct protoent p, *r; char buffer[BUF_SIZE]; while (!getprotoent_r(&p, buffer, BUF_SIZE, &r)) { VALUE alias_array = rb_ary_new(); for (; *p.p_aliases != NULL; p.p_aliases++) { rb_ary_push(alias_array, rb_str_new2(*p.p_aliases)); } rb_yield(rb_struct_new(self, rb_str_new2(p.p_name), alias_array, INT2NUM(p.p_proto))); } } void Init_proto() { VALUE np_mNet, cNetProto; np_mNet = rb_define_module("Net"); cNetProto = rb_struct_define(NULL, "name", "aliases", "proto", 0); rb_extend_object(cNetProto, rb_mEnumerable); rb_define_const(np_mNet, "Proto", cNetProto); rb_set_class_path(cNetProto, np_mNet, "Proto"); rb_define_singleton_method(cNetProto, "getprotobyname", np_getprotobyname, 1); rb_define_singleton_method(cNetProto, "getprotobynumber", np_getprotobynumber, 1); rb_define_singleton_method(cNetProto, "getprotoent", np_getprotoent, 0); rb_define_singleton_method(cNetProto, "[]", np_aref, 1); rb_define_singleton_method(cNetProto, "each", np_getprotoent, 0); }
-- Nobu Nakada