Question regarding rb_include_module

D

Daniel Berger

Hi all,

Ruby 1.8.1
Windows 2000

For the next release of win32-process, I'm getting rid of the toplevel
Win32 module/namespace. Thus, you can do "Process.fork" instead of
"Win32::process.fork". However, I would like to be able to just do
"fork" (no 'Process') in the same manner that you can on *nix. In
pure Ruby I would do something like this:

module Process
def fork
puts "fork!"
end
end

class Object
include Process
end

fork # -> "fork!"

I can't get this to work on the C side, however. I tried this at the
end of "Init_process()":

rb_include_module(rb_cObject,rb_mProcess);

But, it didn't seem to work. What am I not seeing?

Regards,

Dan

/* Full Init_process() */
void Init_process()
{
child_pids = rb_ary_new();

/* Does platform support CreateRemoteThread? */
os_supported = crt_supported();
fname = rb_gv_get("$0");
path = rb_file_s_expand_path(1, &fname);

/* Classes */
cProcessError = rb_define_class_under(rb_mProcess,"Win32::processError",
rb_eRuntimeError);

/* Constants */
rb_define_const(rb_mProcess,"VERSION",rb_str_new2(WIN32_PROCESS_VERSION));

/* Class Methods */
rb_define_singleton_method(rb_mProcess,"kill",process_kill,-1);
rb_define_singleton_method(rb_mProcess,"fork", process_fork, 0);
rb_define_singleton_method(rb_mProcess,"wait", process_wait, 0);
rb_define_singleton_method(rb_mProcess,"wait2", process_wait2, 0);
rb_define_singleton_method(rb_mProcess,"waitpid", process_waitpid,
-1);
rb_define_singleton_method(rb_mProcess,"waitpid2",
process_waitpid2, -1);

// Doesn't work
rb_include_module(rb_cObject,rb_mProcess);
}
 
H

Hal Fulton

Daniel said:
But, it didn't seem to work. What am I not seeing?

Hmm, I'm not much on C extensions. But did you try adding it to Kernel
instead of Object? That would make sense to me. Am I wrong?

Hal
 
D

Daniel Berger

Hal Fulton said:
Hmm, I'm not much on C extensions. But did you try adding it to Kernel
instead of Object? That would make sense to me. Am I wrong?

Hal

I tried that first, actually, but it doesn't work. Upon further
review, Ruby's process.c declares fork() as a method of Process and as
a global function. I think it's mixed into Kernel (or Object, I dunno
- I'm confused now).

Anyway, daz's suggestion prompted me to look closer at process.c to
see how it works and I just ended up doing the same thing - declare it
as both a module method and a global function.

Strange that I can't emulate the pure Ruby behavior on the C side,
though.

Thanks.

Dan
 
N

nobu.nokada

Hi,

At Tue, 11 May 2004 11:18:54 +0900,
Daniel Berger wrote in [ruby-talk:99808]:
module Process
def fork
puts "fork!"
end
end

This defines instance method, but followings do singletons.
 
D

daz

Daniel said:
[...] In pure Ruby I would do something like this:

module Process
def fork
puts "fork!"
end
end

class Object
include Process
end

fork # -> "fork!"

I can't get this to work on the C side, however. I tried this at the
end of "Init_process()":

rb_include_module(rb_cObject,rb_mProcess);

But, it didn't seem to work. What am I not seeing?

Regards,

Dan

In your example, you define fork as an instance method.

In your ext, you defined fork etc. as singleton_methods which
are not considered by #include for mixing in; so rb_include_module
had nothing to work on (except the VERSION constant).

Anyway, you've since fixed that and released it so this is just in
case it was still nagging :)


BTW: Much credit to yourself, Park Heesob, Shanko et al. for
providing these utils. I hope that some of the restructuring
was in preparation for submitting fork for inclusion into core.
It was one of those eternal things that Ruby had missing in
the Windows builds.


daz
 
D

daz

Oops, sorry. I see Nobu has answered.

That post was left in my Outbox from yesterday.


daz
 
D

Daniel Berger

daz said:
In your ext, you defined fork etc. as singleton_methods which
are not considered by #include for mixing in; so rb_include_module
had nothing to work on (except the VERSION constant).

I'm confused then (and I'm tired as I'm writing this). In Ruby's
process.c, the fork function is defined as a singleton of the Process
module, yet somehow it ends up as a method of Kernel. How? I tried
to trace it but I'm not seeing it.

In any case, thanks for that tidbit - I never knew that for some
reason. I should redefine most of those methods as module functions
in the same manner as Ruby's Process module.
BTW: Much credit to yourself, Park Heesob, Shanko et al. for
providing these utils. I hope that some of the restructuring
was in preparation for submitting fork for inclusion into core.
It was one of those eternal things that Ruby had missing in
the Windows builds.

Thank you. I don't think it will be included with core Ruby, but it
might end up in the Ruby Installer for Windows from Curt, Andy & crew,
which is fine by me, and is indeed part of the reason for the
restructuring. Someone would have to fork Ruby to have it included in
the core code, however, and it won't be me. Hmm...what's ActiveState
up to these days? ;)

Thanks.

Dan
 
D

daz

Daniel said:
I'm confused then (and I'm tired as I'm writing this). In Ruby's
process.c, the fork function is defined as a singleton of the Process
module, yet somehow it ends up as a method of Kernel. How? I tried
to trace it but I'm not seeing it.

Confusion is contagious :)

I'm looking at your process.c -- you've added:
rb_define_global_function("fork", process_fork, 0);
as suggested - and it works.


PickAxe (Extending Ruby/Ruby C Language API) says:
------------------------------------------------------------------------
void rb_define_global_function(char *name, VALUE(*func)(), int argc)

Defines a global function (a private method of Kernel) with the given
name, implemented by the C function func and taking argc arguments.
------------------------------------------------------------------------

So you give two distinct ways of invoking the same C function:
Process.fork
& fork (Object#fork - [Object has the Kernel module mixed in])

In Ruby, these are two different methods pointing to the same code
in your extension. When you just type "fork", it doesn't matter if
the Process.fork class method exists or not; it's unconnected.


#----------------------------------------------------------------------
# This snippet "is" rb_define_global_function("fork", my_Knife_code, 0)
# BTW, it overwrites the real fork method (compare below)
#----------------
module Kernel
def fork
puts 'Knife (Kernel)'
end
end
#----------------
fork #=> Knife (Kernel)


# Compare to this - which mixes the Kernel definition of fork
# into an anonymous superclass and blocks direct access to it
# by defining a method with the same name:
#----------------
class Object
def fork
puts 'spOOn (Object)'
super # call the mix-in version
end
end
#----------------

fork #=> spOOn (Object)
#=> Knife (Kernel)

#--- END --------------------------------------------------------------

(If anyone sees problems with that code/description, please correct me.
There is so much going on behind the scenes that it's hard not to
make it appear complicated when it's really very simple.)


=====
I don't think [fork] will be included with core Ruby, but it
might end up in the Ruby Installer for Windows from Curt, Andy & crew,
which is fine by me, and is indeed part of the reason for the
restructuring.
Someone would have to fork Ruby to have it included in
the core code, however, and it won't be me.

Thanks.

Dan


Fork Ruby <question mark> [children run to their homes]

<pseudo>
#ifdef HAVE_FORK
# ifdef _WIN32
/* insert wizard fork stuff here instead of calling ... */
rb_notimplement();
# endif
#endif

The normal thing, IIUC, is to patch process.c and post it to
ruby-core and nervously await the inevitable rejection :/
(only joking -core). But only the author(s) can do that.

Then, when the result is 32 in favour and 0 against, if it
doesn't get accepted we can throw rotten tomatoes at those
responsible for our disappointment, as is customary :)-?)

OTOH, if it's shown to be stable and the author(s) make it clear
that they would be happy to see it added to Process, it might save
the ruby-dev team the trouble of begging you to let them use
your code. They seem much too polite to steal it from you :)


With that said, I have to make it clear that I speak with no
authority, at best.


Cheers,

daz
 
N

nobu.nokada

Hi,

At Fri, 14 May 2004 19:33:53 +0900,
daz wrote in [ruby-talk:100266]:
<pseudo>
#ifdef HAVE_FORK
# ifdef _WIN32
/* insert wizard fork stuff here instead of calling ... */
rb_notimplement();
# endif
#endif

It should be:

#ifdef HAVE_FORK
/* existing code */
#elif defined _WIN32
/* insert wizard fork stuff here. */
#else
rb_notimplement();
#endif
The normal thing, IIUC, is to patch process.c and post it to
ruby-core and nervously await the inevitable rejection :/
(only joking -core). But only the author(s) can do that.

At first, do you really want "fork", not open3 and so on, e.g.,
addition to Process.spawn?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,201
Latest member
KourtneyBe

Latest Threads

Top