2011-11-07 4 views
6

J'essaie de faire en sorte que ce code en ligne Ruby C http://pastie.org/2825882 fonctionne. Le code fonctionne en vanille C, mais ici je reçois des erreurs et des avertissements. Qu'est-ce qui cause cette erreur?Compilation du code C en ligne Ruby - résolution des erreurs

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

En outre, pourquoi j'obtiens l'erreur suivante?

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

observant le code C résultant (http://pastie.org/2826036) Je ne vois rien de mal avec les arguments. Mais je reçois également les avertissements suivants:

./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 
+0

Il visse mon installation rubis tout en expérimentant :) – RocketR

Répondre

5

A partir de ceci:

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

Si vous regardez votre code généré, la fonction backtrack est définie sur la ligne 29:

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

Il a sept arguments, les six originaux, plus VALUE self comme il a été converti en une méthode sur la classe Scan.

L'appel à cette fonction, sur la ligne 67 ressemble à ceci:

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

Il n'a que six arguments. RubyInline ne convertit pas cela en un appel à une méthode sur l'objet, il le copie simplement textuellement. C'est également de là que proviennent les avertissements concernant makes integer from pointer without a cast: la définition de la fonction a été convertie pour prendre VALUE s, mais vous appelez avec les types d'origine.

Le message d'erreur indique que l'erreur est de la ligne 73 dans backtrack_inline.rb en raison de la directive sur la ligne 54 du code généré:

# line 61 "./backtrack_inline.rb" 

qui indique essentiellement le compilateur de « réinitialiser » les valeurs de ligne et le fichier pour les erreurs, et traitez la ligne suivante (55) comme étant la ligne 61 dans le fichier ./backtrack_inline.rb. La ligne réelle est 67, 12 en avant de 55, mais le compilateur le signale comme étant 73, 12 en avant de 61 (la valeur à laquelle il a été réinitialisé) et d'un fichier differnt. Cette technique ne fonctionne pas vraiment dans ce cas car elle ne prend pas en compte les lignes supplémentaires ajoutées par RubyInline. La ligne réelle dans la source est 69.

Une solution simple pour cela est de changer la définition de la fonction backtrack pour qu'elle soit juste une fonction C plutôt que de l'ajouter en tant que méthode sur l'objet. Remplacez builder.c par builder.prefix (sur la ligne 38 de votre fichier Ruby). Cela ne fonctionnera pas si vous souhaitez avoir backtrack disponible en tant que méthode sur l'objet dans Ruby. Si c'est le cas, vous pourriez avoir besoin de créer une autre fonction pour la méthode, qui enveloppe alors la fonction "réelle" de retour arrière.

Ensuite, regardant

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

Cela fait référence à la ligne 61 du code généré, qui ressemble à:

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

StringValuePtr est un macro which is defined as:

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

Cette est où le & en lvalue required as unary '&' operand vient de. Vous devez ajouter une variable locale à la lvalue:

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

ces deux modifications Dans mon cas (Mac OS X Snow Leopard, Ruby 1.9.3-p0, RubyInline 3.11.0) a fait l'exécution du script sans erreurs , mais a donné l'avertissement:

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

Cela fait référence à la ligne 46 du fichier ruby:

return (s - ss) - 1; 

s et ss sont char *, soit 64 bits pointe rs (sur cette machine), et le type de retour de la fonction est int - 32 bits. Ajout d'un casting explicite fixe ceci:

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

Il fonctionne maintenant proprement:

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

(je l'espère 14 est la bonne réponse!)

est ici un version of the script with these changes.

0

Ok ... réfléchi un peu plus à ce sujet.

vous appelez une extrémité variable. Bien que ce ne soit pas un mot réservé dans C - et ruby ​​ne devrait pas le regarder ... peut-être que ruby ​​devient confus?

Je vous suggère d'essayer de le renommer juste au cas où. Il vaut la peine d'essayer même de l'exclure.

Questions connexes