Pull to refresh

Comments 35

Вы игнорируете лучшее в Rust. Типажи бесплатны в бинарном виде, но позволяют описать ожидания от входного типа без учёта его конкретики. В зависимости от того, что важнее - скорость или размер бинарного файла, вы можете использовать динамические трейты (dyn traits) или статические. Статические быстрее, но увеличивают размер бинарного файла, динамические делают дополнительный lookup по таблице методов, зато не вызывают распухания из-за мономорфизации.

Использование пустых типов для усиления типизации - это одна из важных особенностей языка. Вы можете объявить типы без значений и требовать их себе на вход для обеспечения соблюдения протоколов вызова (например, можно иметь Token(), в отсутствтие которого вызов не возможен, а ownership которого позволяет автоматически избежать race conditions).

Мой совет, нырнуть глубже во все эти Vec'и и сплайсы - в них сила, даже если в финале у вас не будет Vec'а.

Спасибо! динамические типы dyn точно работают при отсутствии кучи?

&dyn Trait
fn f(x: &dyn std::fmt::Display) {
  println!("{}", x);
}

fn main() {
  f(&"test");
  f(&1);
}

Я не совсем хорошо понимаю о чём я говорю, но dyn traits - это такой метод присобачить к типу dispatch table, которая устроена таким образом: пользователи под динамическими трейтами (которые принимают dyn trait) на уровне магии компилятора знают какая функция в какое смещенеи ведёт. Каждый провайдер динамического трейта (я не помню, каждого типа или каждого вызова функции с динамическим трейтом) записывает в соответствии с этой магией таблицу вызовов. Вроде бы, она создаётся во время компиляции и хранится в rodata.

Но, может быть, я несу ахинею, потому что я в Rust новичок.

Всё вы правильно написали, но можно написать проще: dyn traits — это такой метод присобачить к ссылке таблицу виртуальных функций. Поскольку ссылка может указывать куда угодно, а таблица виртуальных функций собирается один раз компилятором и хранится в rodata — никакой кучи не требуется.

Эм, не один. Хотя бы потому, что у каждого типа своя таблица вызовов. Более того, если функция хочет иметь у типа два динамических трейта через плюсик, то с табличками всё становится ещё интереснее.

Использование Result<> для возврата ошибок. Наверное это удобно, когда стек вызовов глубокий и активно применяется оператор “?”

Так же оператор ? можно использовать вместе с Optional, если ошибки не важны а нужно только наличие результата.

Умные книги советуют для унификации передачи кодов ошибок опять же применять Box<>, которого в embedded нет.

А ещё можно для этого использовать кастомный Enum, опционально для удобства обьявить его как ошибку (c помощью трейта Error) и оборачивать им все остальные ошибки.

enum MyErrorCode {
    Failed = 1,
    ...
}

enum MyError {
    CodeError(MyErrorCode),
    ATError(ATLibraryError),
    STMError(STMLibraryError),
    ...
}

impl Error for MyError {
    ...
}

Интересная мысль, попробую

Добавлю: если реализовать для MyError типажи From<ATLibraryError> и From<STMLibraryError> — оператор "?" учтёт возможность такого преобразования.

Ну я уже не стал перегружать деталями. В своих проектах я даже макрос писал, который генерировал сам enum, делал From для содержимого и прочие дополнительные description методы.

Крейт `thiserror` это самое и делает из коробки, очень удобно.

thiserror, как я понимаю, требует std, а она недоступна в embedded

thiserror не всегда подходит, да я и не против потренироваться самому макросы писать.

UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here

И ещё почти 4 килобайта можно сэкономить, если перейти с флотов на fixed point, 16.16 вам за глаза должно хватить.

Что то пропустил видимо в статье, но не понял чем компилируется исходник на Rust и чем отлаживается?

Так и не увидел выводов: изначальный замысел в стабильности в embedded у вас вышел относительно С? Вообще слабое звено ч тут вижу SIM800, как и другие версии этих модулей.

Да, я думаю у меня были косяки в коде на C. Длительные испытания планирую с весны, сейчас старый модуль работает. Там видно будет, достигну стабильности или нет

У меня есть вопрос, а зачем использовать Rust в таком небольшом проекте? Тут и чистого си вполне достаточно. Не то чтобы я критикую, интересна мотивация.

Вопрос снят, нашёл в статье - из интереса и попробовать

UFO just landed and posted this here
UFO just landed and posted this here

На расте просто меньше вероятность написать программу, приводящую к разрушению памяти

UFO just landed and posted this here

Не придётся, благо занимающаяся этим группа не сидела без дела рассказывая какой замечательный Rust сам по себе, а давно придумала PAC (Peripheral Access Crate).


Как и зачем оно устроено можно почитать тут: https://docs.rust-embedded.org/book/peripherals/index.html

UFO just landed and posted this here

Таки отличаются — если на железе нет MMU, то, скорее всего, никакого SIGSEGV не будет в принципе, и программа будет работать непредсказуемо.


А паника возникнет надёжно, и так же надёжно будет обработана, пусть даже вся обработка будет заключаться в аварийном останове.

У меня есть вопрос, а зачем использовать Rust в таком небольшом проекте?

А почему размер проекта имеет значение? Если бы код писался на С++, а не на расте вопрос всё равно возник бы? Ну или можно вывернуть другую сторону: "зачем использовать С в таком небольшом проекте, разве асма недостаточно?"


Признаюсь честно, я предвзят, но спрашиваю тоже без критики и агрессии. (:

В данном случае всё более менее норм, и против плюсов на МК ничего не имею, когда они применяются осознанно, с пониманием как это делать правильно и что можно а что недопустимо на МК, просто иногда веселит когда говорят, "мы тут решили помигать парой диодиков и прочитать ацп, с помощью ***какая-то новомодная фича***, но 256кБ это слишком мало для этого =)

п.с. можно сразу отдельный комп поставить на I7

Rust повышает качество жизни (система типов, времена жизни) без принципиальных накладных расходов. Да, автор статьи столкнулся с жирными бинарями, но тут в комментах уже почти полностью разобрались, откуда вытек жир, и как его сжечь.
Sign up to leave a comment.

Articles