27

Writing such library will I have to sacrifice std? How, for example, will do I write python bindings to rust library, if possible?

Moonwalker
  • 2,180
  • 1
  • 29
  • 48
  • 3
    Short version: it's just as good as C, better in most places. The long version I am not well suited to writing, but I've pinged someone who's worked with Ruby/Rust interop (Yehuda Katz, for [Skylight](http://skylight.io).) – Chris Morgan May 21 '14 at 13:07

1 Answers1

44

First, indicate to Rust that you want to create a function visible to C:

#[no_mangle]
pub extern "C" fn some_func() { ... }

This tells Rust to avoid mangling the output symbol and to use the C ABI.

Next, you will need to use C-compatible types when crossing the boundary. Here is some advice that has worked for me:

  • If you are planning to pass a Rust structure to C as opaque data, which it will pass back into other functions, return it as a Box<T>, and take it as a &T or Box<T>. Essentially, this means that you are giving up ownership of the structure in Rust, and giving ownership to the C code. The C code must ensure that if it passes the pointer back into a function that takes a Box, it no longer uses it.
  • If you are planning to pass a Rust structure to C as a C structure, Rust conveniently represents its structs in a C-compatible way. However, you will want to restrict the kinds of values you put in these structs to types that also have compatible C representations. Numeric types and booleans are safe, of course.
  • You can see the Rust representation of more complex types (like vecs and strings) in the docs under core::raw. A &str and &[T] are represented as raw::Slice while a Vec<T> is represented as a raw::Vec.
  • You can also convert types into the libc::types
  • Finally, you may find yourself needing to work with pointers directly. Check out std::mem for useful APIs.
Vladimir Matveev
  • 120,085
  • 34
  • 287
  • 296
Yehuda Katz
  • 28,535
  • 12
  • 89
  • 91
  • 7
    While structs are currently C-compatible in layout, they will not be for much longer, by default; [an RFC was just accepted which will change the layout to undefined unless you use `#[repr(C)]` on the struct](https://github.com/rust-lang/rfcs/blob/0fc8bc0a2d098dc6f007e53f5da20cf11934a297/active/0018-undefined-struct-layout.md). – Chris Morgan May 22 '14 at 02:15
  • Isn't `core::raw::Vec` the representation for an old-style `~[T]` vector? I think `Vec` proper now has a different representation (`{length,capacity,pointer-to-array-of-T}` instead of `pointer-to-{length,capacity,array-of-capacity-Ts}`). –  May 23 '14 at 16:00
  • Could you give example code? I'm not sure I follow. I write library in Rust, make some functions "C"-like, and those functions later can be used to, say, making python bindings, because from python point of view this functions are indistinguishable from ordinary C functions, correct? – Moonwalker May 25 '14 at 18:00
  • So it is safe to have a `pub extern` function that returns a `Box` and then receive the same value from C code as `&T`/`&mut T`? Doesn't require conversion? (Makes sense if the internal representation of a `Box` *really is* a zero cost abstraction). I guess I'll just try it and see. – zstewart Oct 24 '15 at 06:08