The Rust FFI guide (http://static.rust-lang.org/doc/master/guide-ffi.html) nicely demonstrates how to import C functions that use standard C types that are wrapped by the Rust std::lib
library, such as size_t
. But how do I bring C data structures defined in third party libraries into a Rust program?
I'm working with libmemcached, which has the following function:
memcached_st* memcached_create(memcached_st *ptr)
which is typically invoked like so in a C program (to kick things off):
#include <libmemcached/memcached.h> // ... memcached_st *memc; memc = memcached_create(NULL);
The memcached_st
is an opaque C struct - how do I declare and use that in a Rust program? Here are my failed attempts so far:
use std::libc::*; use ptr; #[link(name = "memcached")] extern { struct memcached_st; // error: unexpected token: `struct` memcached_st* memcached_create(memcached_st *ptr); } fn main() { unsafe { let memc = memcached_create(ptr:null()); println!("{:?}", memc); } }
and
use std::libc::*; use ptr; #[link(name = "memcached")] extern { // error: unexpected token: `memcached_st` memcached_st* memcached_create(memcached_st *ptr); } fn main() { unsafe { let memc = memcached_create(ptr:null()); println!("{:?}", memc); } }
We can pass a struct to a function by specifying the struct name as the type in the parameter list. We can return a struct from a function by specifying the struct name as the return type. We can define functions that are specific to a struct, called methods, that can only be used by instances of that struct.
This module provides utilities to handle data across non-Rust interfaces, like other programming languages and the underlying operating system. It is mainly of use for FFI (Foreign Function Interface) bindings and code that needs to exchange C-like strings with other languages.
Rust natively supports linking against C libraries and calling their functions directly. Of course, any function imported thus requires the unsafe keyword to actually call (because Rust can't guarantee its invariants or correctness) but that's an inconvenience we can punt until later.
Structs in Rust come in three flavors: Structs with named fields, tuple structs, and unit structs. Regular structs are the most commonly used. Each field defined within them has a name and a type, and once defined can be accessed using example_struct. field syntax.
Using empty structure is a valid approach. You almost got it, you just don't need to put the struct definition in extern
block. Also you can't use C code inside Rust sources - extern definitions have to follow standard Rust syntax.
use std::ptr; struct memcached_st; #[link(name = "memcached")] extern { fn memcached_create(ptr: *memcached_st) -> *memcached_st; } fn main() { unsafe { let memc = memcached_create(ptr::null()); println!("{:?}", memc); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With