Permalink
Switch branches/tags
Nothing to show
Nothing to show
Commits on Dec 3, 2018
-
bonzini committed
Dec 3, 2018 -
"rustify" implementation, with bindings provided as extern functions
bonzini committedDec 3, 2018 Finally in this patch we complete the exercise and we are able to enjoy the benefits of Rust in implementing the Foo data structure. The data structure is still defined in a C header, and the "bindgen::foo:Foo" struct that bindgen created for us is still what gets re-exported as "foo::Foo". However, it now grows Rust methods, including a constructor "Foo::new" that was not even there in the original C API, and the C API becomes a simple wrapper that converts the raw pointers to C code and calls those methods. In this commit we add a second test, which calls those Rust methods instead of relying on the C API. Note that this test does not have to use any unsafe block, and in fact none of the code added in this commit does.
-
replace with Rust implementation
bonzini committedDec 3, 2018 In this commit, the foo_get and foo_set functions switch to a Rust implementation. Even though bindgen still generates the prototypes for them in "bindgen::foo", we do not re-export them from "foo". Instead, "foo" implements the functions that C code will call. They are marked as "no_mangle" which is essentially the Rust equivalent of C++'s extern "C". Note that the implementation is unsafe; it has to be for two reasons. First, because it dereferences a raw pointer ("let foo = &*foo" and the similar assignment in foo_set) that could be pointing to garbage or to freed data---and this is unsafe, so much that the code would not compile at all if those dereferences were not "unsafe". Second, because we have no idea of what could be in the struct, for example it might be uninitialized. This is not something that the compiler tells us, we have to figure it out! Note that this is probably not a step that you would do explicitly, in practice. As long as you have tests for the C API written in either Rust or C, you can switch directly to a Rust implementation as in the next patch. -
add Rust bindings to the C library
bonzini committedDec 3, 2018 In this commit, we start integrating the C and Rust code; in particular, we keep the C implementation and add Rust tests for it. The Rust library grows two modules, "foo" and "bindgen::foo". The former provides the public API, while the latter is the automatically generated code from bindgen. We do this already, even though for now the public API is just forwarding the bindgen struct and entry points using "pub use". Separating the automatically generated code into the bindgen module lets us disable some errors that make no sense for bindgen code, so it's a good idea. We also need to link the C code into the Rust tests. Doing this requires adding a build.rs file. This Rust source file produces two directives for cargo, essentially corresponding to -L and -l on the linker command line.
-
integrate Cargo into the Makefile
bonzini committedDec 3, 2018 Here we add a Rust library, just like one for which "cargo new --lib" creates the scaffolding, to the project's build system. The Rust library creates another static library, and the Makefile takes care of linking it into the main program. For simplicity we will let Cargo run the build of the Rust parts, but since the project is still first and foremost a C one, the overall build will be driven by "make". Therefore, after this commit you will be able to do "make check" and see some Rust tests run. At this point, the C code is already linking to the Rust library, but the Rust library however is not able to use the C code; this will change in the next commit.
-
bonzini committed
Dec 3, 2018 The C code consists of a trivial library with three functions. This commits adds the library (src/foo.c and src/foo.h), a program that uses it, and a Makefile to build it. The plan is to move two of them (foo_get and foo_set) to Rust, while keeping the third (foo_print) in C. Both C and Rust code must be able to access the entire implementation, because the program will remain in C, while the tests will be in Rust and will want to call foo_print. The conversion to Rust is pretty smooth, because there are no ownership issues---the data structure is entirely self-contained. There is only one prerequisite for the API to be nicely usable from Rust code, which is to use "const" properly in "foo_get", "foo_set" and "foo_print".
NewerOlder