2016-05-07 4 views
1

Я хочу перенести небольшую библиотеку, написанную на C с Python C API, в чистую библиотеку/приложение C. В конце концов, я хочу, чтобы это работало на C++, но я думал, что он лучше работает, не зависимо от python, прежде чем сосредоточиться на том, чтобы получить его на C++.Проблема с портированием библиотеки Python C на «чистую» C

Это кусок кода, который я хочу, чтобы порт: https://github.com/adafruit/Adafruit_DotStar_Pi/blob/master/dotstar.c

Это контролирует определенный тип светодиодов над SPI. На практике можно управлять многими тысячами светодиодов с помощью этой части кода. Он отлично работает в Python, но мой портированный код для приложения C просто ничего не делает, как только я выхожу за пределы 256 светодиодов. С ниже 256 светодиодов все работает нормально.

Поэтому мне кажется, что проблема с типом или распределением, по какой-то причине, не вызывает нарушения доступа к памяти. Мое тестовое приложение не падает, светодиоды просто ничего не делают, когда выходят за порог 256.

У меня есть два фрагмента кода, где я просто не уверен на 100%, что делал Python, что я заменил своим лучшим образованным предположением.

Все данные для светодиодов хранятся в структуре DotStarObject, поэтому я подозреваю, что проблема связана с этой структурой.

Во-первых, я удалил макрос PyObject_HEAD из структуры DotStarObject, насколько я понимаю, все это добавляет некоторые вещи, которые Python необходимо внутренне.

Далее я изменил способ распределения структуры при вызове функции DotStar_new.

Во-первых, я изменил тип функции от static PyObject *DotStar_new до static DotStarObject *DotStar_new, когда он возвращает указатель на структуру DotStarObject.

Виновник, который, как мне кажется, вызывает мою ошибку, является частью, где структура заполнена данными. Обычно Python выделяет здесь некоторую память. Насколько я понял Pythons tp_alloc все, что он делает, выделяет память размера используемого типа (в этом случае DotStarObject).

Так что это:

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); 
     } 
    } 

стал этим (пока отсутствует гарантию при выделении для self терпит неудачу):

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; 
    } 

ли я неправильно, что (DotStarObject *)type->tp_alloc(type, 0) делал или я substitue правильно с DotStarObject *self = (DotStarObject*)malloc(sizeof(DotStarObject));?

Мой полный код можно найти здесь, если я пропустил некоторые cruical информацию: http://pastebin.com/xddN9JMs

+0

Нет языка «C/C++»! Только два ** разных ** языка C и C++, поэтому просить «чистый C/C++» бесполезно. – Olaf

+0

Это действительно сбивает с толку. Я изменил название. Я только добавил C++, потому что там, где я хочу идти, но я думаю, это не важно для вопроса. Я знаю, что это разные языки. – PTS

+0

Если вы будете использовать Ruby-код, если хотите действительно код Brainfuck, нет, это не имеет значения. В противном случае это очень хорошо. Задайте вопрос, который хотите использовать, и используйте для этого соответствующий код. – Olaf

ответ

3

Ну для одной вещи, которую я бы заподозрить этот цикл:

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

Вы используете тип 8-битного для индекса, который позволяет использовать только 256 значений независимо от значения dotty->numLEDs.

+0

О, это на самом деле очень пошло. Я не уверен, произошло ли это до или после того, как я попал в проблему, поскольку я часто менял свой тестовый код. Он может быть недавно добавлен и не связан, но я проверю это и отчитаю/приму ответ. – PTS

+0

Я чувствую себя довольно глупо. Это действительно проблема. Большое спасибо за то, что вы это заметили так быстро! – PTS