2016-05-07 2 views
1

Ich möchte eine kleine Bibliothek, die in C mit der Python C-API geschrieben wurde, in eine reine C-Bibliothek/Anwendung portieren. Am Ende möchte ich, dass dies in C++ funktioniert, aber ich dachte, es wäre besser, es ohne die Python-Abhängigkeit arbeiten zu lassen, bevor ich mich darauf konzentriere, es in C++ zu bekommen. Problem mit der Portierung der Python C-Bibliothek auf "pure" C

Dies ist das Stück Code, den ich in dem Hafen will: https://github.com/adafruit/Adafruit_DotStar_Pi/blob/master/dotstar.c

Dies steuert eine bestimmte Art von LEDs über SPI. In der Praxis kann man mit diesem Code viele tausend LEDs steuern. Es funktioniert großartig in Python, aber mein portierter Code zu einer C-Anwendung tut einfach nichts, sobald ich über 256 LEDs hinausgehe. Mit unter 256 LEDs funktioniert alles gut.

So scheint mir entweder ein Typ Problem oder Zuordnungsproblem, das aus irgendeinem Grund keine Speicherzugriffsverletzung verursacht. Meine Testanwendung stürzt nicht ab, die LEDs tun einfach nichts, wenn sie über den 256-Schwellenwert hinausgehen.

Ich habe zwei Teile Code, wo ich einfach nicht 100% sicher bin, was Python machte, das ich mit meiner besten Vermutung ersetzte.

Alle Daten für die LEDs ist in einer Struktur namens DotStarObject gespeichert, so vermute ich das Problem mit dieser Struktur zu tun haben.

Zuerst habe ich den PyObject_HEAD-Makro aus der DotStarObject-Struktur entfernt, so weit ich es verstehe, all dies fügt einige Dinge hinzu, die Python intern benötigt.

Als nächstes habe ich die Art und Weise geändert, wie die Struktur zugewiesen wird, wenn die DotStar_new-Funktion aufgerufen wird.

Zuerst habe ich den Funktionstyp von static PyObject *DotStar_new zu static DotStarObject *DotStar_new geändert, da es einen Zeiger auf DotStarObject struct zurückgibt.

Der Täter, von dem ich denke, dass er meinen Fehler verursacht, ist der Teil, in dem die Struktur mit Daten gefüllt ist. Normalerweise würde Python hier etwas Speicher reservieren. Soweit ich Pythons tp_alloc verstanden habe, wird nur die Größe des verwendeten Typs zugewiesen (DotStarObject in diesem Fall).

So folgt aus:

PyTypeObject *type; 
DotStarObject *self = NULL; 
(...) 
// Allocate space for LED data: 
    if((!n_pixels) || ((pixels = (uint8_t *)malloc(n_pixels * 4)))) { 
     if((self = (DotStarObject *)type->tp_alloc(type, 0))) { 
      self->numLEDs = n_pixels; 
      self->dataMask = 0; 
      self->clockMask = 0; 
      self->bitrate = bitrate; 
      self->fd   = -1; 
      self->pixels  = pixels; // NULL if 0 pixels 
      self->pBuf  = NULL; // alloc'd on 1st use 
      self->dataPin = dPin; 
      self->clockPin = cPin; 
      self->brightness = 0; 
      self->rOffset = rOffset; 
      self->gOffset = gOffset; 
      self->bOffset = bOffset; 
      Py_INCREF(self); 
     } else if(pixels) { 
      free(pixels); 
     } 
    } 

dies wurde (für jetzt, fehlt den Schutz bei Zuteilung für self ausfällt):

DotStarObject *self = (DotStarObject*)malloc(sizeof(DotStarObject)); 
(...) 
if((!n_pixels) || ((pixels = (uint8_t *)malloc(n_pixels * 4)))) { 
      self->numLEDs = n_pixels; 
      self->dataMask = 0; 
      self->clockMask = 0; 
      self->bitrate = bitrate; 
      self->fd   = -1; 
      self->pixels  = pixels; // NULL if 0 pixels 
      self->pBuf  = NULL; // alloc'd on 1st use 
      self->dataPin = dPin; 
      self->clockPin = cPin; 
      self->brightness = 0; 
      self->rOffset = rOffset; 
      self->gOffset = gOffset; 
      self->bOffset = bOffset; 
    } 

Habe ich falsch interpretieren, was (DotStarObject *)type->tp_alloc(type, 0) tat oder habe ich substitue es richtig mit DotStarObject *self = (DotStarObject*)malloc(sizeof(DotStarObject));?

Mein vollständiger Code kann hier gefunden werden, wenn ich einige cruical Informationen verpaßt: http://pastebin.com/xddN9JMs

+0

Es gibt keine Sprache "C/C++"! Nur die zwei ** verschiedenen Sprachen C und C++, also die Frage nach "reinem C/C++" ist nutzlos. – Olaf

+0

Das ist in der Tat verwirrend. Ich habe den Titel geändert. Ich habe nur C++ hinzugefügt, weil das ist, wo ich am Ende gehen will, aber ich denke, es ist nicht wichtig für die Frage. Ich bin mir bewusst, dass dies verschiedene Sprachen sind. – PTS

+0

Wenn Sie Ruby-Code verwenden würden, wenn Sie eigentlich Brainfuck-Code wollten, ist das egal. Ansonsten tut es sehr gut. Fragen Sie nach der Frage, die Sie verwenden möchten, und verwenden Sie den entsprechenden Code dafür. – Olaf

Antwort

3

Gut für eine Sache, die ich diese Schleife vermuten würde:

for (uint8_t i = 0; i < dotty->numLEDs; ++i){ 
    // setPixelColor(dotty,i,r,g,b);   
    setPixelColor(dotty,i,r,0,0); 
} 

Sie verwenden einen 8-Bit-Typen für den Index, der nur 256 Werte unabhängig vom Wert von dotty->numLEDs erlaubt.

+0

Oh, das ist das eigentlich sehr obivous. Ich bin mir nicht sicher, ob dies vor oder nach dem Treffer passiert ist, da ich meinen Testcode ziemlich oft geändert habe. Es könnte nur kürzlich hinzugefügt werden und nicht zusammenhängen, aber ich werde das überprüfen und die Antwort zurückmelden. – PTS

+0

Ich fühle mich verdammt dumm. Das war in der Tat das Problem. Vielen Dank, dass du es so schnell gefunden hast! – PTS