Init_xxx(with arg ?) in C for ruby ext?

hey all,

new to C, i'm writing a ruby ext, i wonder if we could pass an arg to
Init_xxx(type * arg) ???

this is to have a constructor in ruby like that :

trick=MyClass.new("my arg")

and if not does exists a workaround ???

···

--
une bévue

The Init_ method initializes the shared library, it is not the constructor.

Write your #initialize to take arguments and MyClass.new "my arg" will work.

···

On Aug 8, 2006, at 9:45 AM, Une bévue wrote:

hey all,

new to C, i'm writing a ruby ext, i wonder if we could pass an arg to
Init_xxx(type * arg) ???

this is to have a constructor in ruby like that :

trick=MyClass.new("my arg")

and if not does exists a workaround ???

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

it is :

    rb_define_singleton_method(rb_cMyClass, "new", cd_new, 1);

···

Une bévue <pere.noel@laponie.com.invalid> wrote:

ew to C, i'm writing a ruby ext, i wonder if we could pass an arg to
Init_xxx(type * arg) ???

this is to have a constructor in ruby like that :

trick=MyClass.new("my arg")

and if not does exists a workaround ???

--
une bévue

No. MyClass.new is inherited from Class.

rb_define_method(rb_cMyClass, "new", cd_initialize, 1);

It works "just like" regular ruby.

···

On Aug 8, 2006, at 10:25 AM, Une bévue wrote:

Une bévue <pere.noel@laponie.com.invalid> wrote:

ew to C, i'm writing a ruby ext, i wonder if we could pass an arg to
Init_xxx(type * arg) ???

this is to have a constructor in ruby like that :

trick=MyClass.new("my arg")

and if not does exists a workaround ???

it is :

    rb_define_singleton_method(rb_cMyClass, "new", cd_new, 1);

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

Oops.

rb_define_method(rb_cMyClass, "initialize", cd_initialize, 1);

···

On Aug 8, 2006, at 12:13 PM, Eric Hodel wrote:

On Aug 8, 2006, at 10:25 AM, Une bévue wrote:

Une bévue <pere.noel@laponie.com.invalid> wrote:

ew to C, i'm writing a ruby ext, i wonder if we could pass an arg to
Init_xxx(type * arg) ???

this is to have a constructor in ruby like that :

trick=MyClass.new("my arg")

and if not does exists a workaround ???

it is :

    rb_define_singleton_method(rb_cMyClass, "new", cd_new, 1);

No. MyClass.new is inherited from Class.

rb_define_method(rb_cMyClass, "new", cd_initialize, 1);

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

[snip]

Oops.

rb_define_method(rb_cMyClass, "initialize", cd_initialize, 1);

ok thanks, i get it, now i've an init like that :

VALUE method_raliasfile_init(VALUE self, char * alias_path)
{
   rb_iv_set(self, "@alias_path", *alias_path);
   return self;
}

declared in :

void Init_raliasfile() {
   cRAliasFile = rb_define_class("RAliasFile", rb_cObject);
   rb_define_singleton_method(cRAliasFile, "new", method_raliasfile_new, 1);
   rb_define_method(RAliasFile, "initialize", method_raliasfile_init, 1);
   rb_define_method(RAliasFile, "alias_path", method_alias_path, 0);
   rb_define_method(RAliasFile, "orig_path", method_orig_path, 0);
   rb_define_method(RAliasFile, "is_alias_file", method_is_alias_file, 0);
   rb_define_method(RAliasFile, "is_alias_broken", method_is_alias_broken, 0);
   rb_define_method(RAliasFile, "is_folder", method_is_folder, 0);
   rb_define_method(RAliasFile, "is_data_file", method_is_data_file, 0);
}

and i want the arg "alias_path" to be "global" to all of the methods of this class, what to do for that ???

best,

Yvon

···

Le 9 août 06 à 00:21, Eric Hodel a écrit :

On Aug 8, 2006, at 12:13 PM, Eric Hodel wrote:

[snip]

Oops.

rb_define_method(rb_cMyClass, "initialize", cd_initialize, 1);

ok thanks, i get it, now i've an init like that :

VALUE method_raliasfile_init(VALUE self, char * alias_path)
{
  rb_iv_set(self, "@alias_path", *alias_path);
  return self;
}

declared in :

void Init_raliasfile() {
  cRAliasFile = rb_define_class("RAliasFile", rb_cObject);
  rb_define_singleton_method(cRAliasFile, "new", method_raliasfile_new, 1);

^^^ remove this line ^^^

You don't need to define new.

···

On Aug 8, 2006, at 3:55 PM, Yvon Thoraval wrote:

Le 9 août 06 à 00:21, Eric Hodel a écrit :

On Aug 8, 2006, at 12:13 PM, Eric Hodel wrote:

  rb_define_method(RAliasFile, "initialize", method_raliasfile_init, 1);
  rb_define_method(RAliasFile, "alias_path", method_alias_path, 0);
  rb_define_method(RAliasFile, "orig_path", method_orig_path, 0);
  rb_define_method(RAliasFile, "is_alias_file", method_is_alias_file, 0);
  rb_define_method(RAliasFile, "is_alias_broken", method_is_alias_broken, 0);
  rb_define_method(RAliasFile, "is_folder", method_is_folder, 0);
  rb_define_method(RAliasFile, "is_data_file", method_is_data_file, 0);
}

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

Hi,

At Wed, 9 Aug 2006 07:55:52 +0900,
Yvon Thoraval wrote in [ruby-talk:207182]:

VALUE method_raliasfile_init(VALUE self, char * alias_path)
{
   rb_iv_set(self, "@alias_path", *alias_path);
   return self;
}

All arguments are passed as VALUE, not C type.

VALUE method_raliasfile_init(VALUE self, VALUE alias_path)
{
    rb_iv_set(self, "@alias_path", alias_path);
    return self;
}

···

--
Nobu Nakada

i get an eror now :
RAliasFile.c: In function 'method_alias_path':
RAliasFile.c:46: error: request for member 'alias_path' in something not
a structure or union

then, i think i have to do something like that :
typedef struct _raf {
  int is_alias_file;
  int is_folder;
  int is_data_file;
  char * alias_path;
  char * orig_path;
  char * version;
} RAliasFile;

···

Eric Hodel <drbrain@segment7.net> wrote:

> void Init_raliasfile() {
> cRAliasFile = rb_define_class("RAliasFile", rb_cObject);
> rb_define_singleton_method(cRAliasFile, "new",
> method_raliasfile_new, 1);

^^^ remove this line ^^^

You don't need to define new.

--
une bévue

then this arg "VALUE alias_path" will be common to all of the methods i
have ?

it seems not (???)

i've change my init for debugg purpose to :

VALUE m_raliasfile_init(VALUE self, VALUE alias_path)
{
printf("m_raliasfile_init");
printf((char *)alias_path);
printf("alias_path");
  rb_iv_set(self, "@alias_path", alias_path);
  return self;
}

and, when i use my class from ruby i do :

a=RAliasFile.new("/Users/yvon/work/Ruby/Native/C/doc/Introduction_ANSI_C
_html")
puts a.alias_path

the print out (from C) being :

m_raliasfile_initalias_path

which means the arg "alias_path" isn't pass to "m_raliasfile_init"

the ruby line "puts a.alias_path" gives :

ArgumentError: NULL pointer given

where the C counterpart being :
VALUE m_alias_path(VALUE self) {
// char *alias_path = "/path/to/something/undefined";
  return rb_str_new2((char *) alias_path);
}

what i want is my class "RAliasFile" being initialize like that (from
ruby) :

a=RAliasFile.new("/Users/yvon/work/Ruby/Native/C/doc/Introduction_ANSI_C
_html")

the parameter of "new" being alias_path bar in the C counterpart...

i'm a newb in C as you can see, that's (will be) my first extension..

···

<nobu@ruby-lang.org> wrote:

All arguments are passed as VALUE, not C type.

VALUE method_raliasfile_init(VALUE self, VALUE alias_path)
{
    rb_iv_set(self, "@alias_path", alias_path);
    return self;
}

--
une bévue

Post your *complete* source

where the C counterpart being :
VALUE m_alias_path(VALUE self) {
// char *alias_path = "/path/to/something/undefined";
  return rb_str_new2((char *) alias_path);
}

This is just a nonsense. You define an instance variable @alias_path then
you try to retrieve a local C variable alias_path rather than the instance
variable.

Guy Decoux

ok thanks a lot for your clear answer :wink:

--- RAliasFile.h--------------------------------------------------------
void Init_raliasfile();

VALUE m_raliasfile_init(VALUE self, VALUE alias_path);
VALUE m_raliasfile_new(VALUE self, VALUE alias_path);
VALUE m_set_alias_path(VALUE self, VALUE alias_path);
VALUE m_alias_path(VALUE self);
VALUE m_orig_path(VALUE self);
VALUE m_is_alias_file(VALUE self);
VALUE m_is_alias_file_broken(VALUE self);
VALUE m_is_folder(VALUE self);
VALUE m_is_data_file(VALUE self);
VALUE m_version(VALUE self);

···

ts <decoux@moulon.inra.fr> wrote:

Post your *complete* source

> where the C counterpart being :
> VALUE m_alias_path(VALUE self) {
> // char *alias_path = "/path/to/something/undefined";
> return rb_str_new2((char *) alias_path);
> }

This is just a nonsense. You define an instance variable @alias_path then
you try to retrieve a local C variable alias_path rather than the instance
variable.

------------------------------------------------------------------------
--- RAliasFile.c--------------------------------------------------------
//
// RAliasFile.c
//

#include "ruby.h"
#include "RAliasFile.h"

VALUE RAliasFile = Qnil;
VALUE cRAliasFile;
VALUE alias_path;

/**/
struct RAliasFile {
  VALUE alias_path;
  char *orig_path;
  int alias_file;
  int alias_file_broken;
  int folder;
  int data_file;
  char *version;
};
/**/

void Init_raliasfile() {
  cRAliasFile = rb_define_class("RAliasFile", rb_cObject);
  rb_define_method(RAliasFile, "initialize",
m_raliasfile_init, 1);
  rb_define_method(RAliasFile, "new",
m_raliasfile_new, 1);
  rb_define_method(RAliasFile, "set_alias_path",
m_set_alias_path, 1);
  rb_define_method(RAliasFile, "alias_path", m_alias_path,
0);
  rb_define_method(RAliasFile, "orig_path", m_orig_path, 0);
  rb_define_method(RAliasFile, "is_alias_file", m_is_alias_file,
0);
  rb_define_method(RAliasFile, "is_alias_file_broken",
m_is_alias_file_broken, 0);
  rb_define_method(RAliasFile, "is_folder", m_is_folder, 0);
  rb_define_method(RAliasFile, "is_data_file", m_is_data_file,
0);
  rb_define_method(RAliasFile, "version", m_version, 0);
}

VALUE m_raliasfile_init(VALUE self, VALUE _alias_path)
{
  alias_path = _alias_path;
  printf("From C => alias_path : %s\n", alias_path);
  rb_iv_set(self, "@alias_path", alias_path);
  return self;
}

VALUE m_raliasfile_new(VALUE self, VALUE _alias_path) {
rb_iv_set(self, "@alias_path", alias_path);
printf("m_raliasfile_new");
  alias_path = _alias_path;
  return self;
}

VALUE m_set_alias_path(VALUE self, VALUE _alias_path) {
  alias_path = _alias_path;
  rb_iv_set(self, "@alias_path", alias_path);
// return rb_str_new2((char *) alias_path);
}

VALUE m_alias_path(VALUE self) {
// char *alias_path = "/path/to/something/undefined";
  return rb_str_new2((char *) alias_path);
}

VALUE m_orig_path(VALUE self) {
  char *orig_path = "/Users/yvon/work/Ruby/Native/RubyInline-3.5.0.gem";
  return rb_str_new2(orig_path);
}

VALUE m_is_alias_file(VALUE self) {
  int alias_file = 1;
  return INT2FIX(alias_file);
}

VALUE m_is_alias_file_broken(VALUE self) {
  int alias_file_broken = 0;
  return INT2FIX(alias_file_broken);
}

VALUE m_is_folder(VALUE self) {
  int folder = 0;
  return INT2FIX(folder);
}

VALUE m_is_data_file(VALUE self) {
  int data_file = 0;
  return INT2FIX(data_file);
}

VALUE m_version(VALUE self) {
  char *version = "0.0.1";
  return rb_str_new2(version);
}
------------------------------------------------------------------------
--- raliasfile_test.rb -------------------------------------------------
#!/usr/bin/env ruby
#
# raliastest.rb
#

require 'osx/ralias/raliasfile'

a=RAliasFile.new("/Users/yvon/work/Ruby/Native/C/doc/Introduction_ANSI_C
_html")

#From C => alias_path :

a.set_alias_path("/Users/yvon/work/Ruby/Native/C/doc/Introduction_ANSI_C
_html")

puts a.alias_path
# =>

puts a.orig_path
# => /Users/yvon/work/Ruby/Native/RubyInline-3.5.0.gem

puts a.is_alias_file
# => 1

puts a.is_alias_file_broken
# => 0

puts a.is_folder
# => 0

puts a.is_data_file
# => 0

puts a.version
# => 0.0.1
------------------------------------------------------------------------

note that, for the time being this class do nothing, just want to return
the input value (alias_path). However this is the "skeleton" of what i
need to do and exists allready in ObjC.
--
une bévue

/**/
struct RAliasFile {
  VALUE alias_path;
  char *orig_path;
  int alias_file;
  int alias_file_broken;
  int folder;
  int data_file;
  char *version;
};
/**/

Useless actually because you use instance variable rather than C struct.

If you really want to use C struct, see Data_Make_Struct() and the
examples given in README.EXT or ruby-x.x.x/ext/*

void Init_raliasfile() {
  cRAliasFile = rb_define_class("RAliasFile", rb_cObject);
  rb_define_method(RAliasFile, "initialize",
m_raliasfile_init, 1);
  rb_define_method(RAliasFile, "new",
m_raliasfile_new, 1);

     remove this method #new

  rb_define_method(RAliasFile, "set_alias_path",

                                  ^^^^^^^^^^^^^^^
                                  "alias_path="

m_set_alias_path, 1);
  rb_define_method(RAliasFile, "alias_path", m_alias_path,
0);
  rb_define_method(RAliasFile, "orig_path", m_orig_path, 0);
  rb_define_method(RAliasFile, "is_alias_file", m_is_alias_file,

                                  ^^^^^^^^^^^^^^^
                                  "is_alias_file?",

0);
  rb_define_method(RAliasFile, "is_alias_file_broken",
  rb_define_method(RAliasFile, "is_folder", m_is_folder, 0);
  rb_define_method(RAliasFile, "is_data_file", m_is_data_file,
0);

     same here

VALUE m_raliasfile_init(VALUE self, VALUE _alias_path)
{
  alias_path = _alias_path;

   remove this variable alias_path

  printf("From C => alias_path : %s\n", alias_path);

  You have a VALUE not a char *, you must first convert it to (char *)
  before trying to print it (with, for example, StringValuePtr(), see
  README.EXT)

  rb_iv_set(self, "@alias_path", alias_path);
    
     rb_iv_set(self, "@alias_path", _alias_path);

  return self;
}

VALUE m_raliasfile_new(VALUE self, VALUE _alias_path) {
rb_iv_set(self, "@alias_path", alias_path);
printf("m_raliasfile_new");
  alias_path = _alias_path;
  return self;
}

Useless actually : remove it

VALUE m_set_alias_path(VALUE self, VALUE _alias_path) {
  alias_path = _alias_path;
  rb_iv_set(self, "@alias_path", alias_path);
// return rb_str_new2((char *) alias_path);
}

VALUE m_alias_path(VALUE self) {
// char *alias_path = "/path/to/something/undefined";
  return rb_str_new2((char *) alias_path);

You have defined an instance variable : retrieve it. *Don't* use a global
C variable when you work with instance variable

     return rb_iv_get(self, "@alias_path");

}

VALUE m_orig_path(VALUE self) {
  char *orig_path = "/Users/yvon/work/Ruby/Native/RubyInline-3.5.0.gem";
  return rb_str_new2(orig_path);
}

VALUE m_is_alias_file(VALUE self) {
  int alias_file = 1;
  return INT2FIX(alias_file);

     return Qtrue or Qfalse (not a Fixnum)

}

Guy Decoux

···

ts <decoux@moulon.inra.fr> wrote:

ok, thanks for all and the time u spend about that, my "skeleton"'s
working now...

···

ts <decoux@moulon.inra.fr> wrote:

Qfalse

--
une bévue