Инициализация структуры typedef из библиотеки C в C ++

1

Я хочу включить библиотеку в свой проект C++ (управляет светодиодными полосками RGB на малине Pi). Импорт библиотеки работает нормально, но у меня есть проблема с правильной инициализацией некоторых структур. Я довольно потерян там, где даже нашел правильный синтаксис, я много гуглеров, но не очень далеко.

Сначала я хочу получить пример приложения, который поставляется с библиотекой. См. Https://github.com/richardghirst/rpi_ws281x/blob/master/main.c.

Моя главная проблема в этом. Как мне сделать то, что делается ниже C++?

ws2811_t ledstring =
{
    .freq = TARGET_FREQ,
    .dmanum = DMA,
    .channel =
    {
        [0] =
        {
            .gpionum = GPIO_PIN,
            .count = LED_COUNT,
            .invert = 0,
            .brightness = 255,
        },
        [1] =
        {
            .gpionum = 0,
            .count = 0,
            .invert = 0,
            .brightness = 0,
        },
    },
};

Способ инициализации имеет значение C и не компилируется ни в одном текущем стандарте C++. См.: Почему C++ 11 не поддерживает указанный список инициализаторов как C99? До сих пор я использовал только свои собственные структуры и никогда не использовал typedef, поэтому я просто путаю то, как здесь определяются структуры.

Таким образом определяется структура (ы), которая инициализируется выше. См. Https://github.com/richardghirst/rpi_ws281x/blob/master/ws2811.h

typedef struct
{
    int gpionum;                          //< GPIO Pin with PWM alternate function
    int invert;                           //< Invert output signal
    int count;                            //< Number of LEDs, 0 if channel is unused
    int brightness;                       //< Brightness value between 0 and 255
    ws2811_led_t *leds;                   //< LED buffers, allocated by driver based on count
} ws2811_channel_t;

typedef struct
{
    struct ws2811_device *device;                //< Private data for driver use
    uint32_t freq;                               //< Required output frequency
    int dmanum;                                  //< DMA number _not_ already in use
    ws2811_channel_t channel[RPI_PWM_CHANNELS];
} ws2811_t;

Я пробовал это:

ws2811_led_t matrix[WIDTH][HEIGHT];
ws2811_channel_t channel0 = {GPIO_PIN,LED_COUNT,0,255,*matrix};
ws2811_t ledstring = {nullptr,TARGET_FREQ,DMA,channel0};

Это компилируется, но приводит к ошибке malloc, когда я нахожусь на самом деле "визуализировать" светодиодную полосу:

int x, y;

for (x = 0; x < WIDTH; x++)
{
    for (y = 0; y < HEIGHT; y++)
    {
        cout << "LEDs size: " << (y * WIDTH) + x << endl;
        ledstring.channel[0].leds[(y * WIDTH) + x] = matrix[x][y];
    }
}

Результаты в этом сообщении об ошибке после завершения контура цикла:

malloc(): memory corruption (fast): 0x021acaa8
  • 0
    Инициализатором для channer0 может быть {GPIO_PIN,0,LED_COUNT,255,*matrix} .
  • 0
    Также я замечаю, что вы не определяете channel1 . В C-коде channel представляет собой массив из 2 элементов. Это намеренно?
Показать ещё 1 комментарий
Теги:
struct

2 ответа

4
Лучший ответ

Вы должны использовать использование следующего инициализатора:

ws2811_t ledstring =
{
    nullptr,
    TARGET_FREQ,
    DMA,
    {
        { GPIO_PIN, 0, LED_COUNT, 255 },
        { 0 }
    }
};
  • 0
    Это прекрасно отвечает на вопрос в вашем названии. Мой пост посвящен вероятным причинам повреждения памяти.
  • 0
    Повреждение памяти также исчезло при использовании этой инициализации. Я предполагаю, что библиотека сама справляется с этим, и я каким-то образом препятствовал этому, передавая объект, а не опуская его.
1

Эта строка

ledstring.channel[0].leds[(y * WIDTH) + x] = matrix[x][y];

почти наверняка является причиной повреждения памяти, поскольку это может произойти только при переполнении буфера или разыменовании недействительного (но не NULL) указателя.

Я вижу некоторые проблемы в этом коде

ws2811_channel_t channel0 = {GPIO_PIN,LED_COUNT,0,255,*matrix};
ws2811_t ledstring = {nullptr,TARGET_FREQ,DMA,channel0};

Во-первых, в инициализаторе для channel0 вы устанавливаете поле leds на содержимое matrix[0][0] а не на его адрес. Вы должны изменить окончательный инициализатор как просто matrix.

Затем вы инициализируете channel0.leds чтобы указать на matrix двухмерного массива, но рассматривая ее как одномерный массив в ledstring.channel[0].leds[(y * WIDTH) + x]. Вероятно, это должно быть ledstring.channel[0].leds[x][y].

Наконец, последний инициализатор для ledstring должен быть {channel0} для ясности. Это не большая проблема, но она позволяет вам инициализировать несколько записей в массиве.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню