SPI_IOC_MESSAGE (N) макрос дает мне припадки

У меня проблемы с получением программы SPI, над которой я работаю, чтобы вести себя корректно, и, похоже, это проблема макроса SPI_IOC_MESSAGE (N).

Вот пример кода, который НЕ РАБОТАЕТ (ioctl возвращает EINVAL (22)):

std::vector<spi_ioc_transfer> tr;
<code that fills tr with 1+ transfers>
// Hand the transmission(s) off to the SPI driver
if (tr.size() > 0)
{
int ret = ioctl(fd, SPI_IOC_MESSAGE(tr.size()), tr.data());
if (ret < 1)
{
int err = errno;
}
}

Мой тестовый код сейчас создает вектор длиной 1.
Если я явно изменю код на:

int ret = ioctl(fd, SPI_IOC_MESSAGE( 1 ), tr.data());

…тогда ioctl (…) преуспевает, и мои биты идут по трубе.
Глядя на расширение макроса SPI_IOC_MESSAGE в Eclipse, я не понимаю, почему это не радует.

Предложения?

Я кросс-компилирую для Linux / ARM (Beaglebone Black) с 64-битной виртуальной машины Linux, но я не вижу, что это влияет на макрос.

РЕДАКТИРОВАТЬ:
Вот два расширения макроса из препроцессора C

int ret = ioctl(fd, (((1U) << (((0 +8)+8)+14)) | ((('k')) << (0 +8)) | (((0)) << 0) | ((((sizeof(char[((((tr.size())*(sizeof (struct spi_ioc_transfer))) < (1 << 14)) ? ((tr.size())*(sizeof (struct spi_ioc_transfer))) : 0)])))) << ((0 +8)+8))), tr.data());

и буквальное:

int ret = ioctl(fd, (((1U) << (((0 +8)+8)+14)) | ((('k')) << (0 +8)) | (((0)) << 0) | ((((sizeof(char[((((1)*(sizeof (struct spi_ioc_transfer))) < (1 << 14)) ? ((1)*(sizeof (struct spi_ioc_transfer))) : 0)])))) << ((0 +8)+8))), tr.data());

Абсолютно отвратительно, но я не вижу ничего удивительного в том, как tr.size() будет привыкать там.

Изменить, чтобы включить то, что кажется ответом

#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
extern "C" {
#endif
#include <linux/spi/spidev.h>
#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
}
#endif

Обертывание включаемого файла linux SPI в «extern C» дает системе команду относиться к этому разделу как к простому старому C, и это, кажется, позволяет мне вызывать SPI_IOC_MESSAGE( tr.size() ) или же SPI_IOC_MESSAGE( an_int ) и иметь правильную вещь происходит (проверено с помощью пошагового руководства GDB и анализатором сигналов).

4

Решение

Я подозреваю, что проблема может заключаться в этом конкретном самородке, похороненном в макросе:

...sizeof(char[...tr.size()...])...

Отмечая, что код Linux является исключительно C, стандарт C (у меня здесь есть проект C99 n1256) гласит: sizeof оператор, операнд выражения невычисленного, и результат является константой, если тип операнда является массивом переменной длины, в этом случае он оценивается, а результатом является целое число.

Однако стандарт C ++ (C ++ 11 черновик n3242), по-видимому, не дает каких-либо условий, при которых оценивается операнд, а только утверждает, что результат является константой.

Таким образом, похоже, что это может быть одним из углов, где C и C ++ различаются, и компиляция одного из них приводит к неопределенному поведению. В этом случае, я думаю, что выбор заключается либо в том, чтобы просто взломать вашу собственную версию макроса, либо иметь отдельную внешнюю функцию C, которая обертывает ее.

2

Другие решения


По вопросам рекламы [email protected]