2014-04-07 2 views
7

Meine Frage (n) bezieht sich auf das Arbeiten mit Inline-C-Code: ist es notwendig, die Inline-Stack-Funktionen (Inline_Stack_Vars) zu verwenden rein und raus, oder ist es in diesem Kontext sinnvoll, nur eine Variable zu verändern?Perl Inline :: C: Sind Inline_Stack_Vars etc. notwendig, um Speicherlecks zu vermeiden (Biosequenz-Zeichenabgleich)

Für die Anzeige von Biosequenz-Daten, muss ich nur Unterschiede zwischen zwei ausgerichteten Strings zeigen; z.B. gegeben diese beiden Strings:..

ATCAGAAA--GACATGGGCCAAAGATTAA-CAGTGGCCATTGACAGGA-- 
    --CCCCAACTGACAGGGGGCAAAGATTAA-CAGTGGCCATTG---GGA-- 

ich diese (die passenden Zeichen in der zweiten Saite mit‘ersetzt bekommen die

--.CCC..CT....G...G..........-............---...-- 

Ich habe eine Menge von Sequenzen (Millionen von Illumina liest) wird so gedreht für den Charakter passenden Inline :: c der folgende inlined Code ganz gut zu funktionieren scheint (das zweite Argument die add_matchchars Funktion anstelle Wechsel).

#!/usr/bin/perl 
use Inline C; 

my($seq1,$seq2) = qw/ ATCAGAAA--GACATGGGCCAAAGATTAA-CAGTGGCCATTGACAGGA-- 
         --CCCCAACTGACAGGGGGCAAAGATTAA-CAGTGGCCATTG---GGA-- /; 

print $seq1,"\n"; 
print $seq2,"\n"; 
add_matchchars($seq1,$seq2); 
print $seq2,"\n"; 

__END__ 

__C__ 

void add_matchchars(char *seq1, char *seq2) { 
    int seq1char; 
    int seq2char; 
    while(seq1char = *seq1++ , seq2char = *seq2++) { 
     if (seq1char == seq2char) { 
      *seq2--; 
      if (seq1char != '-') { 
       *seq2 = '.'; 
      } 
      *seq2++; 
     } 
     //printf("%c-%c\n",seq1char,seq2char); 
    } 
// printf("%s\n%s\n",seq1,seq2); 
} 

Aber 1) i t einigermaßen effizient (gibt es einen klüger/besseren Weg)? und 2) wird es Speicher verlieren?

+0

'Inline_Stack_ *' ist ein Mittel zum Zugriff auf Variablenlängenlisten. Hat nichts mit Speicherlecks zu tun. – ikegami

+0

Die Inline_Stack _.... sind Makros, die anstelle von Makros der unteren Ebene verwendet werden können, die normalerweise beim Übergeben von Parametern verwendet werden Mit dem Perl XS können Sie auf dem Aufruf-Stack hin und her schalten. Das ist bequem: Wenn Sie auf den Parameter-Aufruf-Stack zugreifen, verwenden Sie entweder diese Makros oder die Untere Ebene XS Makromenge. – DavidO

Antwort

6

Sie sollten sich nicht auf die char * eines Skalars verlassen, der veränderbar ist oder sogar der ursprüngliche Puffer des Skalars ist. Übergeben Sie stattdessen eine neue Zeichenfolge.

Das Makro Inline_Stack_Vars ist nur nützlich, wenn es sich um eine variable Anzahl von Argumenten oder mehrere Rückgabewerte handelt. Dies ist auch hier nicht der Fall.

Ihr Code leidet derzeit nicht unter Speicherlecks (Sie haben keinen Speicher innerhalb Ihrer C-Funktion), aber es gibt einige Probleme inkl. . Stil, möglich segfaults (korrekte while(seq1char = *seq1++ , seq2char = *seq2++)-while((seq1char = *seq1++) && (seq2char = *seq2++)) und die Tatsache, dass Perl Strings NULs innerhalb der Zeichenfolge

enthalten denke ich es in der Regel eine bessere Idee ist Ihre C-Funktion übernehmen Skalare direkt haben rund.

SV *add_matchchars(SV *seq1_sv, SV *seq2_sv) { 
    STRLEN len1, len2; 
    char *seq1 = SvPVbyte(seq1_sv, len1); 
    char *seq2 = SvPVbyte(seq2_sv, len2); 
    STRLEN min_len = len1 < len2 ? len1 : len2; 
    SV *seq3_sv = newSVpvn(seq2, min_len); 
    char *seq3; 
    STRLEN i; 

    seq3 = SvPVX(seq3_sv); 
    for (i = 0; i < min_len; ++i) { 
     if (seq1[i] == seq2[i]) 
      seq3[i] = '.'; 
    } 

    return seq3_sv; 
} 
+1

Dank @ikegami für Ihre Bearbeitungen, ich habe viel von ihnen gelernt :) – amon

+0

np. Wenn Sie '$ seq2' direkt ändern möchten, verwenden Sie' SvPVbyte_force' anstelle von 'SvPVbyte', dann modifizieren Sie' seq2' anstelle von 'seq3'. – ikegami

+0

Dank @amon - diese Art von Feedback ist genau das, was ich brauchte. – user3507704

Verwandte Themen