Struct needs to be a constant?

Hi all,

I whipped this up today. My eyes must be glazing over again, because I’m getting this error:

test.rb:3:in `require’: identifier Proto::ProtoStruct needs to be constant (NameError) from
test.rb:3

where line 3 is simply ‘require “net/proto”’

Any ideas? I think I’ve just been staring at the computer screen too long. Thanks.

Dan

Source:

#include “ruby.h”
#include <netdb.h>
#include <string.h>

#ifdef __cplusplus
extern “C”
{
#endif

#define BUF_SIZE 8192

VALUE cNetProto, sProto;

static VALUE np_getprotobyname(VALUE obj, VALUE proto_name)
{
struct protoent p;
char buffer[BUF_SIZE];
getprotobyname_r(STR2CSTR(proto_name),&p,buffer,BUF_SIZE);
return INT2NUM(p.p_proto);
}

static VALUE np_getprotobynumber(VALUE obj, VALUE proto_number)
{
struct protoent p;
char buffer[BUF_SIZE];
getprotobynumber_r(NUM2INT(proto_number),&p,buffer,BUF_SIZE);
return rb_str_new2(p.p_name);
}

static VALUE np_getprotoent()
{
VALUE alias_array = rb_ary_new();
struct protoent p;
char buffer[BUF_SIZE];

while(getprotoent_r(&p,buffer,BUF_SIZE))
{
for(; *p.p_aliases != NULL; p.p_aliases++)
{
rb_ary_push(alias_array,rb_str_new2(*p.p_aliases));
}

  rb_yield(rb_struct_new(sProto,
     rb_new_str2(p.p_name),
     alias_array,
     INT2NUM(p.p_proto)
  ));

}
}

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);

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);
}

#ifdef __cplusplus
}
#endif

Sample test script

require “net/proto”

puts Net::Proto.getprotobyname(“tcp”).to_s
puts Net::Proto.getprotobynumber(7)

Net::Proto.getprotoent{ |p|
puts p.name
puts p.proto
}

try replacing the last two lines by

sProto = rb_struct_define(“ProtoStruct”,“name”,“aliases”,“number”,0);
rb_define_const(cNetProto, “ProtoStruct”, sProto);

– Gotoken

···

At Thu, 8 Aug 2002 05:27:27 +0900, Daniel Berger 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);

Hi,

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);

}

···

At Thu, 8 Aug 2002 06:01:35 +0900, GOTO Kentaro wrote:


Nobu Nakada