I'm trying to write a C++ library, which is going to target an ARM Linux system, but leaving C-compatible "bindings" and structs for using with CFFI on other languages.
The library deals with a serial stream that I don't control, and that I want to de-serialize.
I have the following (simplified) struct on stream.h
:
#pragma once
#include "cpp_compat.h"
#include <stdbool.h>
#include <stdint.h>
#define BB_FRAME_IQ_SAMPLES_COUNT 512
#define BB_FRAME_MAGIC 0xAA5555AA
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct __attribute__((__packed__))
{
/** Every frame starts with BB_FRAME_MAGIC. */
uint32_t magic;
/** Baseband IQ samples. */
fcomplex_t bb_iq_samples[BB_FRAME_IQ_SAMPLES_COUNT];
uint8_t someparams[9]; // simplification
uint32_t reserved_n[6];
uint32_t crc;
} bb_frame_t;
#ifdef __cplusplus
}
#endif
fcomplex_t
is where the C/C++ compatibility happens, thanks to cpp_compat.h
:
#pragma once
#ifdef __cplusplus
#include <complex>
using fcomplex_t = std::complex<float>;
#else
#include <complex.h>
typedef _Complex float fcomplex_t;
#endif
However, I'm having this warning when building the code in C++:
[build] stream.h:41:37: warning: ignoring packed attribute because of unpacked non-POD field ‘fcomplex_t <unnamed struct>::bb_iq_samples [512]’
[build] 41 | fcomplex_t bb_iq_samples[BB_FRAME_IQ_SAMPLES_COUNT];
[build] | ^~~~~~~~~~~~~
And this scares me because I really need the packed attribute to work to correctly de-serialize the frames from the serial stream.
The compiler is arm-linux-gnueabihf-g++ (GCC) 12.2.1 20221203 [releases/gcc-12 revision c03cb4b762aceeba95da918b042583af0d9f6030]
. I got it from a buildroot using the Linaro toolchain.
So the question is, how can I make this work without errors?
P.S.: It's worth noting that the C++ standard guarantees that std::complex<float>
and _Complex float
are memory-compatible.
EDIT 1: In the meanwhile, I found out that x86's GCC also complains about the issue but Clang (tested with version 16) does not. Seems to be something GCC-specific.
Raised the problem on GCC.
It's apparently an intended behaviour of the compiler.
More details in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108342