Перейти к содержанию
    

Плавный переход C -> C++ под МК

Ну если для вас тут всё смешно, то ничем помочь не могу - этим врачи занимаются.  Вопросы стиля написания - это ж вы подняли, не я. Кому-то там остро не понравились dogygen-блоки, второй подхватил, ну и понеслось. Ну а я то че, я ж говорю - не нравится, не употребляйте, я не насильничаю.

Я и не претендую на степень "неговновости" кода. Вы конечно можете и дальше возиться в ваших устрицах, но лично я, пока тут писал мессаги, дописал код до логического завершения, проверил на паре реальных микросхем на I2C - работает как положено. 

Цитата

"Массивы были в Си, в плюсах классы"... 

Это следует понимать в том ключе, что в Си такая задача описывается структурой struct и массивом переменных с типом этой структуры, а функции, работающие с этими структурами, они независимы и записываются вообще отдельно.
В отличие от этого, в С++ желательно написать класс, включающий в себя структуру регистров внешней микросхемы и методы (функции) работы с этими регистрами. То есть, класс самодостаточен и представляет уже единый объект, а не разрозненные куски. И затем уже можно объекты класса объединить в массив, если нужно.
То есть, переходя на С++, следует не только переключить синтаксис написания, но и образ своего мышления.

Изменено пользователем Variant99

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поздравляю, у меня тоже работает. Я за это время еще и CAN поднял, и GUI на компе накатал для управления.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 hours ago, Arlleex said:

Поздравляю, у меня тоже работает. Я за это время еще и CAN поднял, и GUI на компе накатал для управления.

Это же просто чудо какое-то ! Или магия.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В C++ не работает Си-шный трюк с алиасом типов внутри union?

union uTxMsg {
  struct sSysInf {
    u32 cmd,
        car : 4,
        bls : 1,
        blc : 2,
        crc;
  };
  
  ...
};

static void sendMsg(uTxMsg const *msg, u32 len) {
  ...
}

int main() {
  uTxMsg::sSysInf msg;
  
  sendMsg(&msg, sizeof(msg));
}
Цитата

Error: no matching function for call to 'sendMsg'


Т.е. технически понятно - это C++ со своими перегрузками, однако как красиво из ситуации выйти?

Делаю обобщенный тип uTxMsg для избежания каламбура типов при strict aliasing.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

21 minutes ago, Arlleex said:

Т.е. технически понятно - это C++ со своими перегрузками, однако как красиво из ситуации выйти?

Я бы всю union uTxMsg засунул в другую struct и уже ее передавал в реализации  sendMsg и при создании экземпляров msg

А саму union сделал бы безымянной. Вот нашел у себя на примере CAN фрейма:

namespace stm32f1
{
	class CAN
	{
	public:

		using Frame = struct
		{
			bool 		isExtendedId;
			bool 		isRTR;
			uint32_t 	id;
			uint8_t		dataSize;
			uint8_t 	filterIndex;

			union // 8 bytes strictly
			{
				uint8_t		dataU8[8];
				uint16_t	dataU16[4];
				float		float32[2];
				uint32_t	dataU32[2];
				uint64_t	dataU64;
				double		float64;
			};
		};

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если всю union засовывать в другой объект, объем будет считаться именно этого объекта.

А мне как раз нужна фишка объединения - создавать передаваемое сообщение нужной длины, не больше.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 minutes ago, Arlleex said:

Если всю union засовывать в другой объект, объем будет считаться именно этого объекта.

Так в этом весь смысл union - его длина одинаковая для всего объекта.

 

8 minutes ago, Arlleex said:

А мне как раз нужна фишка объединения - создавать передаваемое сообщение нужной длины, не больше.

union переменной длины? Это как? Покажите пример что нужно, не въезжаю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

19 минут назад, Forger сказал:

union переменной длины? Это как? Покажите пример что нужно, не въезжаю.

Сам union, конечно же, не переменной длинны. А вот его члены-структуры - разной длины.

Я хочу иметь одну функцию sendMsg(), которая принимает аргументами:

1) указатель на данные;

2) длину этих данных.

Передаваемые данные в зависимости от контекста имеют разную структуру (соответственно, и размер).

В соответствии с ограничениями strict aliasing я не могу указывать "принципиально разными" указателями на один и тот же участок памяти.

В Си для решения этой проблемы существует так называемый каламбур типов - делается он с помощью union, куда запихиваются все "сочленяемые" типы. Этот каламбур в дальнейшем используется в описаниях прототипов функций и везде, где требуется разношерстный доступ по разным указателям. А вот в C++ этот трюк выпилили, для него это undefined behavior. Вот я и ищу решение проблемы.

Еще раз: я хочу функцию sendMsg(), в которую пихаю указатели разных типов и она их корректно переваривает без нарушения strict aliasing. Flash/RAM раздувать шаблонными функциями и перегрузками не могу (памяти облом).

Выше я привел код, где функция sendMsg() принимает указатель на обобщенный тип - uTxMsg. А какой конкретно объект ей будет передан определяется по ходу программы, в данном случае я создал структурку uTxMsg::sSysInf, заполнил ее и отправил. uTxMsg здесь как некая библиотека возможных структур, юзер может отправлять только сообщения из этого набора. Саму uTxMsg создавать не хочется, т.к. ее общий объем может быть весьма велик для размещения на стеке конкретной задачи RTOS.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 minutes ago, Arlleex said:

В соответствии с ограничениями strict aliasing я не могу указывать "принципиально разными" указателями на один и тот же участок памяти.

 static_cast 

на край есть reinterpret_cast

20 minutes ago, Arlleex said:

Саму uTxMsg создавать не хочется,

А чем плох указатель на структуру, в которой полно юнионов, как в моем примере?

Если идти дальше в этот "огород, то тут вместо указателей можно применить аж smart pointer, но это для отборных мазохистов ))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что-то насчет этих кастов в интернетах два лагеря - некоторые утверждают, что они решают проблему strict aliasing, другие же, напротив - UB по-прежнему будет...:unknw:

30 минут назад, Forger сказал:

А чем плох указатель на структуру, в которой полно юнионов, как в моем примере?

Так мне же надо создать сначала объект (сообщение конкретного вида), а затем передать его функции.

Я не могу создать объект структуры (общей), т.к. ее размер будет определяться размером самого большого элемента внутри нее.

А меня это не устраивает, т.к. сообщения у меня есть и короткие (десяток байт), и длинные (сотни байт).

Стек задачи, которая отправляет короткое сообщение-ack, не позволит выделить на нем сотни байт "обобщенного" типа-структуры/объединения.

P.S. Со static_cast ругается "error: static_cast from 'uTxMsg::sSysInf *' to 'nsSLIP::uTxMsg *', which are not related by inheritance, is not allowed". На reinterpret_cast, по крайней мере, не ругается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17 minutes ago, Arlleex said:

Что-то насчет этих кастов в интернетах два лагеря

Ну, да эти cast для особых случаев. Это тоже самое приведение типов из C, но со своими особенностями. Годятся для "тонких" мест, но злоупотреблять ими не стоит )

В вашем случае все равно не пойму, зачем нужен именно union?

Насколько я понимаю, union используют для совсем других задач, где размер строго типизирован и можно сказать фиксирован. Неужели без union никак? 

В конце концов сделайте две разные структуры, и два способа работы с ними. Методы для работы с ними я бы вообще засунул в функционал этих структур, буквально внутрь, как методы класса.

На объем самих структур в озу это все равно не влияет, но пользоваться несколько удобнее.

Если идти дальше, то можно создать некое базовое сообщение со своим базовым функционалом, это может быть как структура так и класс.

Он нее наследовать для других, расширяя их возможности. Как вариант

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

15 минут назад, Forger сказал:

В вашем случае все равно не пойму, зачем нужен именно union?

Потому что по задумке это изначально был каламбурный тип, как в Си. Только чуть позже я понял, что в плюсах это уже совсем не так.

Я хотел, чтобы была некая "библиотека" форматов сообщений (union). Я беру конкретный шаблон (структуру) из этой библиотеки, заполняю - отправляю.

А функция отправки принимает любой из допустимых форматов, описанных в этой библиотеке. Соответственно, ее реализация одна, а принимает она некий общий тип.

Я бы давно сделал все это на банальном void *, не будь подвохов со строгим алиасингом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Arlleex сказал:

А функция отправки принимает любой из допустимых форматов, описанных в этой библиотеке. Соответственно, ее реализация одна, а принимает она некий общий тип.

Я бы делал примерно так:

struct sendable
{
    enum class tag { OK };
    static constexpt tag Tag = tag::OK;
};

struct a : public sendable
{
    ..............
};

struct b
{
    ............
};

void send_msg(void const * from, size_t size);

template<typename T>
void send_msg(T const & data)   { if(data.Tag == sendable::tag::OK) send_msg(&data, sizeof(T)); }
  
  
void test()
{
	a Good = {};
  	send_msg(Good);
  
  	b Bad = {};
  	send_msg(Bad);	// <-- compile error Bad has no member 'Tag'
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

18 минут назад, Сергей Борщ сказал:

Я бы делал примерно так...

Идея ясна, спасибо. Мне просто казалось, что финт ушами с union-ом прокатит, т.к. он для меня синтаксически даже понятнее. Ан нет.

Но, опять же, у Вас шаблонная функция, я бы хотел избежать этого. Сама send() у меня будет не совсем тривиальной, т.к. в ней сразу будет осуществляться канальное кодирование. И если компилятор реально создаст тупо 2 копии одной и той же логики, это будет совсем печально.

А вот идея с наследованием структур мне нравится, надо с этим немного поразмыслить.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

42 минуты назад, Arlleex сказал:

Но, опять же, у Вас шаблонная функция, я бы хотел избежать этого

Эта шаблонная функция тупо передает другой (нешаблонной) указатель и размер структуры. Результат проверки известен на этапе компиляции. То есть код шаблонной функции занимает ровно ноль лишних байтов. Вам бы все равно пришлось передавать указатель и размер вручную (с шансом ошибиться). Да, я забыл сделать ее inline, но компилятор, скорее всего, догадается сам.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...