Pull to refresh

Comments 8

Очень хочу попробовать написать несколько DXE-драйверов на Rust, но пока совершенно не хватает времени на то, чтобы сделать нормальный интерфейс хотя бы к UEFI BootServices и RuntimeServices. Плюс язык новый и малознакомый, плюс хитрое calling convention, плюс строки в UCS2 вместо UTF8, и в итоге получается какой-то хлам, а не драйвер, и проще дальше на С писать.
Вопрос к тем, кто уже пробовал писать на Rust действительно системные вещи (bare-metal, к примеру): сильно сложно жить без стандартной библиотеки? Компилятор не вставляет memset и memcpu самостоятельно?
Во-первых все строки на расте в utf-8. По поводу memcpy и memset париться обычно не нужно: раст не даёт использовать неинициализированные переменные (это ошибка компиляции), а значения типов, поддерживающие копирование (реализующие трейт Copy), копируются автоматически. Не копируемые значения перемещаются де факте тоже копированием, но только при передаче за пределы функции, а уже перемещённые значения использовать нельзя, компилятор не даст.

Без стандартной либы жить можно. Можно посмотреть на rustboot для примера. Можно выключить stdlib и оставить только core, тогда будет доступ к самой низкоуровневой функциональности.
Вот именно что в UTF8. А в UEFI — в UCS2, в итоге строковые литералы придется делать через макросы, и простого L«String» уже недостаточно.
По поводу memset и memcpu — в С бывают случаи, когда их вызовы могут быть вставлены компилятором автоматически (к примеру, при передаче по значению структуры, размер которой не кратен никакому доступному регистру), а потом при линковке вдруг оказывается, что таких функций нет. Когда я столкнулся с таким поведением впервые — был немало удивлен, поэтому и спрашиваю.
Я больше прикладной программист, пришёл в раст из питона и скалы, так что про такие детали не в курсе, но вопрос интересный.
А вот и ответ на него:
libcore is built on the assumption of a few existing symbols:

memcpy, memcmp, memset — These are core memory routines which are often generated by LLVM. Additionally, this library can make explicit calls to these functions. Their signatures are the same as found in C. These functions are often provided by the system libc, but can also be provided by the rlibc crate.

rust_begin_unwind — This function takes three arguments, a fmt::Arguments, a &str, and a u32. These three arguments dictate the panic message, the file at which panic was invoked, and the line. It is up to consumers of this core library to define this panic function; it is only required to never return.

Поведение такое же, как в C, и тоже придется либо реализовывать самому, либо использовать библиотеку rlibc, либо обернуть уже доступные gRS->CopyMem и gRS->SetMem.
Ну, судя по всему, автор boot2rust решил эту проблему собственной реализацией memset.
Нормально жить без стандартной библиотеки, libcore вполне хватает для почти всего, что можно вообще сделать без аллокации на куче. Хотелось бы, конечно, шаблонные кастомные аллокаторы у libstd, как в STL, но Box пока еще не устаканился, может позже увидим и такую фичу.
Sign up to leave a comment.

Articles