[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

C socket to Ruby socket

Andre Nathan

9/5/2006 3:53:00 PM

Hello

What is the correct way to convert a C socket (int) to a Ruby Socket
object in a C extension? Something like

int s = socket(...);
VALUE sock = rb_some_func(s);

In my extension there's a callback function that receives a socket as an
argument, and I'd like to pass that socket as an argument to a ruby
block, so I need to convert it to a Socket object first.

Thanks in advance,
Andre


10 Answers

Francis Cianfrocca

9/5/2006 4:02:00 PM

0

On 9/5/06, Andre Nathan <andre@digirati.com.br> wrote:
> Hello
>
> What is the correct way to convert a C socket (int) to a Ruby Socket
> object in a C extension? Something like
>
> int s = socket(...);
> VALUE sock = rb_some_func(s);
>
> In my extension there's a callback function that receives a socket as an
> argument, and I'd like to pass that socket as an argument to a ruby
> block, so I need to convert it to a Socket object first.
>
> Thanks in advance,
> Andre
>
>
>

does it need to be a Socket? class IO can be initialized with a file descriptor.

Andre Nathan

9/5/2006 4:46:00 PM

0

On Wed, 2006-09-06 at 01:02 +0900, Francis Cianfrocca wrote:
> does it need to be a Socket? class IO can be initialized with a file descriptor.

You mean rb_io_initialize()?

It would be nice if it was a socket, and even better if there was a way
to find out if it is a TCPSocket or a UDPSocket, since it's always a
network connection (no UNIXSocket, for example).

Thanks,
Andre


Andre Nathan

9/6/2006 3:10:00 AM

0

Hi!

On Wed, 2006-09-06 at 01:17 +0900, Kent Sibilev wrote:
> You probably can call Socket.for_fd using rb_funcall.

I got it to work with an IO:

rb_funcall(rb_cIO, rb_intern("for_fd"), 1, INT2NUM(socket));

However I can't seem to be able to make rb_cSocket visible to my
extension. Any hints on how to do that?

Thanks,
Andre


Francis Cianfrocca

9/6/2006 3:37:00 AM

0

On 9/5/06, Andre Nathan <andre@digirati.com.br> wrote:
> Hi!
>
> On Wed, 2006-09-06 at 01:17 +0900, Kent Sibilev wrote:
> > You probably can call Socket.for_fd using rb_funcall.
>
> I got it to work with an IO:
>
> rb_funcall(rb_cIO, rb_intern("for_fd"), 1, INT2NUM(socket));
>
> However I can't seem to be able to make rb_cSocket visible to my
> extension. Any hints on how to do that?

You may find this unacceptably ugly, but how about:

char buf[100];
snprintf (buf, sizeof(buf)-1, "Socket.for_fd( %d )", socket);
rb_eval_string (buf);

There was some radio chatter on the core list a few months back about
the fact that rb_cSocket is not externed in ruby.h. As I recall the
omission is an oversight, not something fundamental. You could also
say

extern VALUE rb_cSocket;

in your extension. I've done that before.

Nobuyoshi Nakada

9/6/2006 3:49:00 AM

0

Hi,

2006/9/6, Francis Cianfrocca <garbagecat10@gmail.com>:
> On 9/5/06, Andre Nathan <andre@digirati.com.br> wrote:

> > On Wed, 2006-09-06 at 01:17 +0900, Kent Sibilev wrote:
> > However I can't seem to be able to make rb_cSocket visible to my
> > extension. Any hints on how to do that?

rb_const_get(rb_cObject, rb_intern("TCPSocket"));

> There was some radio chatter on the core list a few months back about
> the fact that rb_cSocket is not externed in ruby.h. As I recall the
> omission is an oversight, not something fundamental. You could also
> say
>
> extern VALUE rb_cSocket;
>
> in your extension. I've done that before.

It doesn't work always on all platforms.

--
Nobu Nakada

Andre Nathan

9/6/2006 11:42:00 AM

0

On Wed, 2006-09-06 at 12:49 +0900, Nobuyoshi Nakada wrote:
> rb_const_get(rb_cObject, rb_intern("TCPSocket"));

That worked, thanks!

> > extern VALUE rb_cSocket;
> >
> > in your extension. I've done that before.
>
> It doesn't work always on all platforms.

Will it eventually be externed in ruby.h then?


Thanks,
Andre


Nobuyoshi Nakada

9/6/2006 3:57:00 PM

0

Hi,

At Wed, 6 Sep 2006 20:41:41 +0900,
Andre Nathan wrote in [ruby-talk:212933]:
> > > extern VALUE rb_cSocket;
> > >
> > > in your extension. I've done that before.
> >
> > It doesn't work always on all platforms.
>
> Will it eventually be externed in ruby.h then?

It isn't the point. Dynamically loaded symbols may not visible
from other loaded libraries.

--
Nobu Nakada

Joel VanderWerf

9/6/2006 8:04:00 PM

0

nobu@ruby-lang.org wrote:
> Hi,
>
> At Wed, 6 Sep 2006 20:41:41 +0900,
> Andre Nathan wrote in [ruby-talk:212933]:
>>>> extern VALUE rb_cSocket;
>>>>
>>>> in your extension. I've done that before.
>>> It doesn't work always on all platforms.
>> Will it eventually be externed in ruby.h then?
>
> It isn't the point. Dynamically loaded symbols may not visible
> from other loaded libraries.
>

Socket is a pretty popular library. Maybe rb_cSocket could be declared
in IO.c?

just a thought, and it would be inelegant...

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Nobuyoshi Nakada

9/7/2006 3:54:00 AM

0

Hi,

At Thu, 7 Sep 2006 05:04:12 +0900,
Joel VanderWerf wrote in [ruby-talk:213012]:
> >>>> extern VALUE rb_cSocket;
> >>>>
> >>>> in your extension. I've done that before.
> >>> It doesn't work always on all platforms.
> >> Will it eventually be externed in ruby.h then?
> >
> > It isn't the point. Dynamically loaded symbols may not visible
> > from other loaded libraries.
> >
>
> Socket is a pretty popular library. Maybe rb_cSocket could be declared
> in IO.c?

It would be popular indeed, but is an extension library, which may or
may not be loaded. By just accessing, it can be zero if it hasn't
been loaded yet. So you need to ensure it got loaded:

rb_require("socket");
rb_funcall(rb_cTCPSocket, rb_intern("for_fd"), 1, INT2NUM(socket));

I guess this might be better with autoloading.

rb_funcall(rb_path2class("TCPSocket"), rb_intern("for_fd"), 1,
INT2NUM(socket));


This is a script to generate autoloading code.


#!./miniruby -s

Top = "rb_cObject"

class String
if File::ALT_SEPARATOR
def proppath
tr!(File::ALT_SEPARATOR, File::SEPARATOR)
self
end
else
def proppath
self
end
end
end
$srcdir.proppath if $srcdir

header = "ruby.h"
header = File.join($srcdir, header) if $srcdir
stdmod = {}
IO.foreach(header) do |line|
if n = line[/^RUBY_EXTERN\s+VALUE\s+(rb_[mc]\w+);/, 1]
stdmod[n] = true
end
end

if ARGV.empty?
ext = "ext"
ext = File.join($srcdir, ext) if $srcdir
dirs = [ext]
else
dirs = ARGV.collect {|d| d.proppath}
end

if $srcdir
srcpre = %r"\A#{Regexp.quote($srcdir)}/"
else
srcpre = /\A/
end

dirs.collect! do |d|
if File.basename(d) == "extconf.rb"
d
else
Dir.glob(File.join(d, "**/extconf.rb"))
end
end
dirs.flatten!
region = " /* begin autoload */"
dirs.each do |e|
if File.directory?(e) and !File.exist?(e = File.join(e, "extconf.rb"))
next
end
comment = "\n /* #{File.dirname(e.sub(srcpre, ''))} */"
modname = IO.read(e)[/create_makefile\s*[\s\(]([\'\"])(.*?)\1\s*\)?/,
2] or next
ARGV.replace(Dir.glob(File.join(File.dirname(e), "*.c")))
ARGF.each do |line|
/\brb_define_(?:class|module)(?:\s*\(|_under\s*\((\w+)\s*,)?\s*("\w+")/
=~ line or next
name, mod = $2, $1
if !mod
mod = Top
elsif !stdmod[mod]
next
end
if comment
if region
puts region
region = nil
end
puts comment
comment = nil
end
puts " rb_autoload(#{mod}, rb_intern(#{name}), \"#{modname}\");"
end
end
puts "\n /* end autoload */" unless region


--
Nobu Nakada

Francis Cianfrocca

9/7/2006 4:17:00 AM

0

On 9/6/06, Nobuyoshi Nakada <nobu@ruby-lang.org> wrote:
> It would be popular indeed, but is an extension library, which may or
> may not be loaded. By just accessing, it can be zero if it hasn't
> been loaded yet. So you need to ensure it got loaded:
>
> rb_require("socket");
> rb_funcall(rb_cTCPSocket, rb_intern("for_fd"), 1, INT2NUM(socket));
>
> I guess this might be better with autoloading.


Nobu, thanks for clearing that up. Now I understand why the more
resolved socket classes are not externed by default.