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 Cheers, Martin
on 2011-11-08 09:04
on 2011-11-08 09:49
It is generally best to send these types of questions to a more targeted medium, like writing the author directly or filing a support ticket on github. On Nov 8, 2011, at 00:04 , Martin Hansen wrote: > 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 This one took me a bit... #define StringValuePtr(v) rb_string_value_ptr(&(v)) and you're using it in: char* s = StringValuePtr(rb_iv_get(self, "@seq")); so you're essentially doing: char* s = rb_string_value_ptr(&rb_iv_get(self, "@seq")); which you can't really do in C. > Also, why do I get the following error? > > ./backtrack_inline.rb:73: error: too few arguments to function > 'backtrack' Because you're passing too few arguments to the function (6 to 7 arity function): static VALUE backtrack(VALUE self, VALUE _ss, VALUE _s, VALUE _p, VALUE _mm, VALUE _ins, VALUE _del) vs: backtrack(ss, s + 1, p + 1, mm - 1, ins, del))) Since you're not actually using self for anything, there is no reason for this to be a registered method. You might want to add this to the prefix section. > 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 This is simply because of the above lack of self, I assume. I changed your code (with the above) like so: # above w/ prefixens builder.add_static "id_seq", 'rb_intern("@seq")', "ID" # in patscan: VALUE seq = rb_ivar_get(self, id_seq); char* s = StringValuePtr(seq); and got '14' as the output (off by 1?).
on 2011-11-08 12:10
I was in doubt whether to use: char* s = StringValuePtr(rb_iv_get(self, "@seq")); or char* s = RSTRING_PTR(rb_iv_get(self, "@seq")) I see now that the first is plain wrong, but what about the latter? When is that used? I tried to apply the suggested changes, but the C code still have "VALUE self" as first argument in the functions. How did you get rid of that?
on 2011-11-08 14:43
On Nov 8, 2011, at 12:10 PM, Martin Hansen wrote: > > I tried to apply the suggested changes, but the C code still have "VALUE > self" as first argument in the functions. How did you get rid of that? Did you change line 38 in http://pastie.org/2825882 from "builder.c %{" to "builder.prefix %{" ? If you don't define backtrack as an instance method, self will not be expected to be passed as first argument.
on 2011-11-08 15:50
Sylvester Keil wrote in post #1030842: How could I know that bulder.c -> builder.prefix changed the function an instance method to a "function"? I am pretty desperate for some reading - and examples - on this matter! Something modern (i. e. Ruby 1.9) and something that is about inline C and not necessarily all of Ruby's API. I changed the code and cleaned up a few things: Ruby code: http://pastie.org/2831055 Inline code: http://pastie.org/2831058 Now I get a warning - and the wrong output: /Users/maasha/.ruby_inline/Inline_Scan_5319.c: In function 'backtrack': /Users/maasha/.ruby_inline/Inline_Scan_5319.c:38: warning: implicit conversion shortens 64-bit value into a 32-bit value false Cheers, Martin > On Nov 8, 2011, at 12:10 PM, Martin Hansen wrote: > >> >> I tried to apply the suggested changes, but the C code still have "VALUE >> self" as first argument in the functions. How did you get rid of that? > > Did you change line 38 in http://pastie.org/2825882 from > > "builder.c %{" to "builder.prefix %{" > > ? > > If you don't define backtrack as an instance method, self will not be > expected to be passed as first argument.
on 2011-11-08 20:49
On Nov 8, 2011, at 03:10 , Martin Hansen wrote: > I was in doubt whether to use: > > char* s = StringValuePtr(rb_iv_get(self, "@seq")); > > or > > char* s = RSTRING_PTR(rb_iv_get(self, "@seq")) > > I see now that the first is plain wrong, but what about the latter? When > is that used? No... it is NOT plain wrong. Trying to use the result of a return value as an lvalue is plain wrong. By putting it in it's own variable, you can use StringValuePtr just fine (and should). > I tried to apply the suggested changes, but the C code still have "VALUE > self" as first argument in the functions. How did you get rid of that? As Sylvester pointed out, you missed my suggestion to make that function a prefixed function.
on 2011-11-08 21:37
On Nov 8, 2011, at 06:50 , Martin Hansen wrote: > Sylvester Keil wrote in post #1030842: > > How could I know that bulder.c -> builder.prefix changed the function an > instance method to a "function"? Well, first, because I showed you: >> Because you're passing too few arguments to the function (6 to 7 arity function): >> >> static >> VALUE backtrack(VALUE self, VALUE _ss, VALUE _s, VALUE _p, VALUE _mm, VALUE _ins, VALUE _del) >> >> vs: >> >> backtrack(ss, s + 1, p + 1, mm - 1, ins, del))) >> >> Since you're not actually using self for anything, there is no reason for this to be a registered method. You might want to add this to the prefix section. > I am pretty desperate for some reading > - and examples - on this matter! Something modern (i. e. Ruby 1.9) and > something that is about inline C and not necessarily all of Ruby's API. If you find the documentation insufficient in some way, please file a ticket. I can only improve what I know about. > false I don't. Here is what I wound up with: #!/usr/bin/env ruby require 'pp' require 'inline' class Scan def initialize(seq) @seq = seq end inline do |builder| builder.prefix %{ #define MATCH(A,B) ((equal[(A)] & equal[(B)]) != 0) } builder.add_static "id_seq", 'rb_intern("@seq")', "ID" builder.prefix %{ int equal[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,14, 4,11, 0, 0, 8, 7, 0, 0,10, 0, 5,15, 0, 0, 0, 9,12, 2, 2,13, 3, 0, 6, 0, 0, 0, 0, 0, 0, 0, 1,14, 4,11, 0, 0, 8, 7, 0, 0,10, 0, 5,15, 0, 0, 0, 9,12, 2, 2,13, 3, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; } # ss is the start of the string, used only for reporting the match endpoints. builder.prefix %{ int backtrack(char* ss, char* s, char* p, int mm, int ins, int del) { int r = 0; while (*s && MATCH(*s, *p)) ++s, ++p; // OK to always match longest segment if (!*p) return (s - ss) - 1; else { if (mm && *s && *p && (r = backtrack(ss, s + 1, p + 1, mm - 1, ins, del))) return r; if (ins && *s && (r = backtrack(ss, s + 1, p, mm, ins - 1, del))) return r; if (del && *p && (r = backtrack(ss, s, p + 1, mm, ins, del - 1))) return r; } return 0; } } # Find all occurrences of p starting at any position in s, with at most # mm mismatches, ins insertions and del deletions. builder.c %{ int patscan(char* p, int mm, int ins, int del) { VALUE seq = rb_ivar_get(self, id_seq); char* s = StringValuePtr(seq); char* ss; int nnd; for (ss = s; *s; ++s) { nnd = backtrack(ss, s, p, mm, ins, del); if (nnd) return nnd; } } } end end seq = "tcatcgagtcatcgatcgatcgatcgatcga" pat = "gtcatcga" scanner = Scan.new(seq) puts scanner.patscan(pat, 0, 0, 0)
on 2011-11-09 10:25
OK, it works now. However, I still get a warning:
warning: implicit conversion shortens 64-bit value into a 32-bit
value
The offending line is return (s - ss) - 1; where I expect an int. How
to make this portable?
And I'd like to contribute with suggestions and ideas. Where is the best
place? Github, rubyforge, a mailing list?
Many thanks!
Martin
on 2011-11-09 10:50
On Nov 9, 2011, at 10:25 AM, Martin Hansen wrote: > OK, it works now. However, I still get a warning: > > warning: implicit conversion shortens 64-bit value into a 32-bit > value > > The offending line is return (s - ss) - 1; where I expect an int. How > to make this portable? IIRC s and ss are pointers to a (the same?) string, right? If they are, then this difference here will easily fit into 32bit so you could cast to int explicitly: return (int)((s - ss) - 1) Or you could change the function definition to return a long instead of int and return a 64bit value on 64bit systems.
on 2011-11-09 14:48
> IIRC s and ss are pointers to a (the same?) string, right? If they are, > then this difference here will easily fit into 32bit so you could cast > to int explicitly: > > return (int)((s - ss) - 1) > > Or you could change the function definition to return a long instead of > int and return a 64bit value on 64bit systems. Yes, that will do. Thanks! Martin
on 2011-11-09 22:54
On Nov 9, 2011, at 01:25 , Martin Hansen wrote: > OK, it works now. However, I still get a warning: > > warning: implicit conversion shortens 64-bit value into a 32-bit > value > > The offending line is return (s - ss) - 1; where I expect an int. How > to make this portable? It shouldn't expect an int. You're returning a measurement. They can't be negative. You should be returning a size_t if anything. > And I'd like to contribute with suggestions and ideas. Where is the best > place? Github, rubyforge, a mailing list? All my stuff is mirrored to github.
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.