Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiling Ruby Inline C code - resolving errors

I am trying to get this Ruby inline C code http://pastie.org/2825882 to work. The code works in vanilla C, but here I get errors and warnings. What causes this error?

./backtrack_inline.rb:67: error: lvalue required as unary '&' operand

Also, why do I get the following error?

./backtrack_inline.rb:73: error: too few arguments to function 'backtrack'

Inspecting the resulting C code ( http://pastie.org/2826036) I fail to see anything wrong with the arguments. But I do also get the following warnings:

./backtrack_inline.rb:73: warning: passing argument 1 of 'backtrack' makes integer from pointer without a cast
./backtrack_inline.rb:73: warning: passing argument 2 of 'backtrack' makes integer from pointer without a cast
./backtrack_inline.rb:73: warning: passing argument 3 of 'backtrack' makes integer from pointer without a cast
like image 893
maasha Avatar asked Nov 07 '11 16:11

maasha


2 Answers

Starting with this:

./backtrack_inline.rb:73: error: too few arguments to function 'backtrack'

If you look at your generated code, the backtrack function is defined on line 29:

static VALUE backtrack(VALUE self, VALUE _ss, VALUE _s, VALUE _p, VALUE _mm, VALUE _ins, VALUE _del) { ... }

It has seven arguments, the original six, plus VALUE self as it has been converted into a method on the Scan class.

The call to this function, on line 67 looks like this:

end = backtrack(ss, s, p, mm, ins, del);

It has only six arguments. RubyInline doesn't convert this to a call to a method on the object, it simply copies it verbatim. This is also where the warnings about makes integer from pointer without a cast come from: the function definition has been converted to take VALUEs, but you're calling with the original types.

The error message says that the error is from line 73 in backtrack_inline.rb because of the directive on line 54 of the generated code:

# line 61 "./backtrack_inline.rb"

which basically tells the compiler to "reset" its line and file values for errors, and treat the next line (55) as being line 61 in the file ./backtrack_inline.rb. The actual line is 67, 12 ahead of 55, but the compiler reports it as being 73, 12 ahead of 61 (the value it was reset to) and from a differnt file. This technique doesn't really work in this case as it doesn't take into account the extra lines added by RubyInline. The actual line in the source is 69.

A simple fix for this is to change the definition of the backtrack function to be just a C function rather than add it as a method on the object. Change builder.c to builder.prefix (on line 38 of your Ruby file). This won't work if you want to have backtrack available as a method on the object in Ruby. If that's the case you might need create another function to be the method, which then wraps the "real" backtrack function.

Next, looking at

./backtrack_inline.rb:67: error: lvalue required as unary '&' operand

This actually refers to line 61 of the generated code, which looks like:

char* s = StringValuePtr(rb_iv_get(self, "@seq"));

StringValuePtr is a macro which is defined as:

#define StringValue(v) rb_string_value(&(v))

This is where the & in lvalue required as unary '&' operand comes from. You need to add a local variable to be the lvalue:

VALUE seq = rb_iv_get(self, "@seq");
char* s = StringValuePtr(seq);

In my case (Mac OS X Snow Leopard, Ruby 1.9.3-p0, RubyInline 3.11.0) these two changes made the script run without errors, but gave the warning:

backtrack_inline.rb:47: warning: implicit conversion shortens 64-bit value into a 32-bit value

This actually refers to line 46 of the ruby file:

return (s - ss) - 1;

s and ss are char *, i.e. 64 bit pointers (on this machine), and the return type of the function is int - 32 bits. Adding an explicit cast fixed this:

return (int)((s - ss) - 1);

It now runs cleanly:

ruby-inline $ ruby backtrack_inline.rb 
14
ruby-inline $ 

(I hope 14 is the correct answer!)

Here's a version of the script with these changes.

like image 113
matt Avatar answered Sep 30 '22 12:09

matt


OK, the question was also answered at Ruby Forum:

http://www.ruby-forum.com/topic/2959614

like image 38
maasha Avatar answered Sep 30 '22 12:09

maasha