I want to include a library in my C++ project (controls RGB LED strips on the Raspberry Pi). Importing the library is working fine but I have quite the issue with properly initializing some structs. I'm pretty lost where to even find the proper syntax, I did a lot of googling but didn't get very far.
What I want to at first is getting the sample application going that comes with the library. See: https://github.com/richardghirst/rpi_ws281x/blob/master/main.c
My main issue is this. How do I do what is done below the C++ way?
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,
},
},
};
The way this is initialized is C specific and doesn't compile in any current C++ standard. See: Why does C++11 not support designated initializer list as C99? So far I only ever used my own structs and also never used typedef, so I'm just confused the way structs are defined here.
The struct(s) that gets initialized above is defined in this way. See: 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;
What I tried was this:
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};
That compiles but results in a malloc error when I come to actually "render" to the LED strip:
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];
}
}
Results in this error message after the loop construct finishes:
malloc(): memory corruption (fast): 0x021acaa8
This line
is almost certainly the cause of the memory corruption, as that can only happen by either a buffer overrun or dereferencing an invalid (but non-NULL) pointer.
I see some problems in this code
First, in the initializer for
channel0
you are setting theleds
field to the contents ofmatrix[0][0]
rather than its address. You need to change the final initializer to be simplymatrix
.Next, you are initializing
channel0.leds
to point to the two dimensional arraymatrix
, but treating it as a single dimensional array inledstring.channel[0].leds[(y * WIDTH) + x]
. This should probably beledstring.channel[0].leds[x][y]
.Finally, the last initializer for
ledstring
should probably be{channel0}
for clarity. That's not a big issue, but it allows you to initialize more than one entry in the array.You should be able to use use following initializer: