为什么当我使用 double 时 Qt<->Matlab 可以正确写入和读取我的字节,但对于存储 uint32 的字节却不正确?
Why are my bytes being written and read properly by Qt<->Matlab when I use doubles, but improperly for my bytes storing uint32?
我正在尝试通过 UDP 将数据包从我的 Qt GUI 应用程序发送到 Mathworks Simulink 模型,并在其中解包。我正在使用联合将数据保存到并将其转换为要发送的 char
字节数组。我的前 58 个字节按预期写入和读取,但最后一部分没有。
我尝试了多种数据类型 (int, unsigned int, float, int32_t
),其中 none 似乎正在写入 m_tx_data.myBytes[]
中的正确字节。
我的猜测是我的代码中出现了一些小问题,或者 Matlab 和 Qt read/write 字节到整数的方式不同,但我不知道是怎么回事。
我定义的联合
const int GUI2DEVICE_NUM_DOUBLE = 7;
const int GUI2DEVICE_NUM_BOOL = 2;
const int GUI2DEVICE_NUM_INT32 = 3;
const int GUI2DEVICE_DATA_SIZE = (GUI2DEVICE_NUM_DOUBLE*sizeof(double)) +
(GUI2DEVICE_NUM_BOOL*sizeof(bool)) +
(GUI2DEVICE_NUM_INT32*sizeof(unsigned int));
union GuiToDeviceDataType
{
char myBytes[GUI2DEVICE_DATA_SIZE];
struct
{
double doub[GUI2DEVICE_NUM_DOUBLE];
bool boolean[GUI2DEVICE_NUM_BOOL];
int32_t int32[GUI2DEVICE_NUM_INT32];
} part;
};
正在为联合赋值。每个变量都将类型匹配到它要去的结构的一部分。 m_tx_data.myBytes
初始化为0。
m_tx_data.part.doub[iAmplitude] = amplitude;
m_tx_data.part.doub[iStartFrequency] = startHz;
m_tx_data.part.doub[iStopFrequency] = stopHz;
m_tx_data.part.doub[iFrequencyRampTime] = FreqRampTime;
m_tx_data.part.doub[iAmpRampUpTime] = AmpRampUpTime;
m_tx_data.part.doub[iAmpRampDownTime] = AmpRampDownTime;
m_tx_data.part.doub[iAutoScaleDecrementPercent] = ASDecPercent;
m_tx_data.part.boolean[0] = 1;
m_tx_data.part.boolean[1] = 1;
m_tx_data.part.int32[iSweepSteps] = SweepSteps;
m_tx_data.part.int32[iPeriodsToAverage] = PeriodsToAverage;
m_tx_data.part.int32[iPeriodsToIgnore] = PeriodsToSkip;
分配给 m_tx_data.part.int32[]
的值等于 1(将它们分配给 2 或 3 return 类似的结果)。我期望 m_tx_data.myBytes[58:61]
为 (0 0 0 1)
或 (1 0 0 0)
(字节序),但它是 returning (0 0 1 0)
,它被读作 65536
Matlab (little endian).
但是,对于我的双打,他们正在按预期保存和阅读。 m_tx_data.myBytes[0:7] = (0 0 0 0 0 0 240 63)
被 Matlab 转换为 double 时读作 1
。
调试和查看 m_tx_data.myBytes 时,我可以看到存储在每个字节中的值,并观察每个变量被写入结构。
添加检查static_assert(sizeof(GuiToDeviceDataType::part) == GUI2DEVICE_DATA_SIZE)
。由于对齐,它应该在您的情况下显示错误。让我们检查一下:
size_t sz1 = sizeof(GuiToDeviceDataType::part);
// sz1 == 72 and GUI2DEVICE_DATA_SIZE is 70
重新排序结构以将 bool
字段移动到结构的末尾,这样您将获得更多预期结果 - 填充应该仅在结构的末尾。您可以通过将指针地址转换为 char*
然后显示差异来检查这一点:
GuiToDeviceDataType data;
size_t sz1 = sizeof(GuiToDeviceDataType::part);
char* p1 = (char*)(void*)&data.part.boolean[0];
char* p2 = (char*)(void*)&data.part.int32[0];
size_t diff = p2 - p1;
std::cout << diff; // shows 4 for your code
我正在尝试通过 UDP 将数据包从我的 Qt GUI 应用程序发送到 Mathworks Simulink 模型,并在其中解包。我正在使用联合将数据保存到并将其转换为要发送的 char
字节数组。我的前 58 个字节按预期写入和读取,但最后一部分没有。
我尝试了多种数据类型 (int, unsigned int, float, int32_t
),其中 none 似乎正在写入 m_tx_data.myBytes[]
中的正确字节。
我的猜测是我的代码中出现了一些小问题,或者 Matlab 和 Qt read/write 字节到整数的方式不同,但我不知道是怎么回事。
我定义的联合
const int GUI2DEVICE_NUM_DOUBLE = 7;
const int GUI2DEVICE_NUM_BOOL = 2;
const int GUI2DEVICE_NUM_INT32 = 3;
const int GUI2DEVICE_DATA_SIZE = (GUI2DEVICE_NUM_DOUBLE*sizeof(double)) +
(GUI2DEVICE_NUM_BOOL*sizeof(bool)) +
(GUI2DEVICE_NUM_INT32*sizeof(unsigned int));
union GuiToDeviceDataType
{
char myBytes[GUI2DEVICE_DATA_SIZE];
struct
{
double doub[GUI2DEVICE_NUM_DOUBLE];
bool boolean[GUI2DEVICE_NUM_BOOL];
int32_t int32[GUI2DEVICE_NUM_INT32];
} part;
};
正在为联合赋值。每个变量都将类型匹配到它要去的结构的一部分。 m_tx_data.myBytes
初始化为0。
m_tx_data.part.doub[iAmplitude] = amplitude;
m_tx_data.part.doub[iStartFrequency] = startHz;
m_tx_data.part.doub[iStopFrequency] = stopHz;
m_tx_data.part.doub[iFrequencyRampTime] = FreqRampTime;
m_tx_data.part.doub[iAmpRampUpTime] = AmpRampUpTime;
m_tx_data.part.doub[iAmpRampDownTime] = AmpRampDownTime;
m_tx_data.part.doub[iAutoScaleDecrementPercent] = ASDecPercent;
m_tx_data.part.boolean[0] = 1;
m_tx_data.part.boolean[1] = 1;
m_tx_data.part.int32[iSweepSteps] = SweepSteps;
m_tx_data.part.int32[iPeriodsToAverage] = PeriodsToAverage;
m_tx_data.part.int32[iPeriodsToIgnore] = PeriodsToSkip;
分配给 m_tx_data.part.int32[]
的值等于 1(将它们分配给 2 或 3 return 类似的结果)。我期望 m_tx_data.myBytes[58:61]
为 (0 0 0 1)
或 (1 0 0 0)
(字节序),但它是 returning (0 0 1 0)
,它被读作 65536
Matlab (little endian).
但是,对于我的双打,他们正在按预期保存和阅读。 m_tx_data.myBytes[0:7] = (0 0 0 0 0 0 240 63)
被 Matlab 转换为 double 时读作 1
。
调试和查看 m_tx_data.myBytes 时,我可以看到存储在每个字节中的值,并观察每个变量被写入结构。
添加检查static_assert(sizeof(GuiToDeviceDataType::part) == GUI2DEVICE_DATA_SIZE)
。由于对齐,它应该在您的情况下显示错误。让我们检查一下:
size_t sz1 = sizeof(GuiToDeviceDataType::part);
// sz1 == 72 and GUI2DEVICE_DATA_SIZE is 70
重新排序结构以将 bool
字段移动到结构的末尾,这样您将获得更多预期结果 - 填充应该仅在结构的末尾。您可以通过将指针地址转换为 char*
然后显示差异来检查这一点:
GuiToDeviceDataType data;
size_t sz1 = sizeof(GuiToDeviceDataType::part);
char* p1 = (char*)(void*)&data.part.boolean[0];
char* p2 = (char*)(void*)&data.part.int32[0];
size_t diff = p2 - p1;
std::cout << diff; // shows 4 for your code