简体   繁体   中英

How to place a C struct on the function stack in Rust?

I would like to transfer the following C code

HMAC_CTX context;
HMAC_CTX_init(&context);

into Rust. But while it's easy to define an extern function, it seems impossible to directly use a C struct in Rust.

extern "C" {
  use HMAC_CTX; // does not work!
  fn HMAC_CTX_init(ctx: *mut HMAC_CTX);
}

I know that I could define a placeholder struct in Rust

struct HMAC_CTX;

...but an instance of may not hold enough space for the real C struct.

let mut ctx = HMAC_CTX;
unsafe { HMAC_CTX_init(&mut ctx); }

Is there a way of solving this without redefining the whole struct in Rust? That would create a dependency from the external code to my Rust project and I would like to avoid this.

Use rust-bindgen to generate Rust bindings. It'll generate a rust version of the corresponding C struct and keep it synchronized if placed in the build-script.

Adds complexity to the build process and adds a dependency.

Create a Rust version of the C struct by hand.

#[repr(C)]
pub struct HMAC_CTX {
  md: *mut EVP_MD,
  md_ctx: EVP_MD_CTX,
  i_ctx: EVP_MD_CTX,
  o_ctx: EVP_MD_CTX,
  key_length: c_uint,
  key: [c_uchar; 128],
}

This requires to follow changes of the C code and manually update the Rust struct. Also further structs might have to be defined. Add a dependency to the internals of the called library:-(

Create a placeholder struct.

pub struct HMAC_CTX {
  _placeholder: [c_uchar; 256],
}

This struct needs to be large enough to hold all the internals of the C struct. Indirect dependency:-( If the C struct size exceeds the placeholder size, it could lead to unsafe behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM