Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Rust how can I define or import a C struct from a third party library?

Tags:

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);     } } 
like image 398
quux00 Avatar asked Mar 01 '14 15:03

quux00


People also ask

How do you pass a struct to a function in Rust?

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.

What is FFI Rust?

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.

Can C library Rust?

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.

Does Rust have structs?

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.


1 Answers

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);     } } 
like image 95
Vladimir Matveev Avatar answered Sep 18 '22 07:09

Vladimir Matveev