---
minutes: 30
---
# Safe FFI Wrapper
Rust has great support for calling functions through a _foreign function
interface_ (FFI). We will use this to build a safe wrapper for the `libc`
functions you would use from C to read the names of files in a directory.
You will want to consult the manual pages:
- [`opendir(3)`](https://man7.org/linux/man-pages/man3/opendir.3.html)
- [`readdir(3)`](https://man7.org/linux/man-pages/man3/readdir.3.html)
- [`closedir(3)`](https://man7.org/linux/man-pages/man3/closedir.3.html)
You will also want to browse the [`std::ffi`] module. There you find a number of
string types which you need for the exercise:
| Types | Encoding | Use |
| -------------------------- | -------------- | ------------------------------ |
| [`str`] and [`String`] | UTF-8 | Text processing in Rust |
| [`CStr`] and [`CString`] | NUL-terminated | Communicating with C functions |
| [`OsStr`] and [`OsString`] | OS-specific | Communicating with the OS |
You will convert between all these types:
- `&str` to `CString`: you need to allocate space for a trailing `\0` character,
- `CString` to `*const i8`: you need a pointer to call C functions,
- `*const i8` to `&CStr`: you need something which can find the trailing `\0`
character,
- `&CStr` to `&[u8]`: a slice of bytes is the universal interface for "some
unknown data",
- `&[u8]` to `&OsStr`: `&OsStr` is a step towards `OsString`, use
[`OsStrExt`](https://doc.rust-lang.org/std/os/unix/ffi/trait.OsStrExt.html) to
create it,
- `&OsStr` to `OsString`: you need to clone the data in `&OsStr` to be able to
return it and call `readdir` again.
The [Nomicon] also has a very useful chapter about FFI.
[`std::ffi`]: https://doc.rust-lang.org/std/ffi/
[`str`]: https://doc.rust-lang.org/std/primitive.str.html
[`String`]: https://doc.rust-lang.org/std/string/struct.String.html
[`CStr`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html
[`CString`]: https://doc.rust-lang.org/std/ffi/struct.CString.html
[`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html
[`OsString`]: https://doc.rust-lang.org/std/ffi/struct.OsString.html
[Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html
Copy the code below to and fill in the missing
functions and methods:
```rust,should_panic,editable
// TODO: remove this when you're done with your implementation.
#![allow(unused_imports, unused_variables, dead_code)]
{{#include exercise.rs:ffi}}
{{#include exercise.rs:DirectoryIterator}}
todo!()
}
}
{{#include exercise.rs:Iterator}}
todo!()
}
}
{{#include exercise.rs:Drop}}
todo!()
}
}
{{#include exercise.rs:main}}
```
FFI binding code is typically generated by tools like [bindgen], rather than
being written manually as we are doing here. However, bindgen can't run in an
online playground.
[bindgen]: https://github.com/rust-lang/rust-bindgen