Mathieu David
Mathieu David

Reputation: 5278

What is the best way to get a `*const c_char` from a const array via FFI?

I am trying to interface with a C API in Rust. They define a couple of string constants with macros:

#define kOfxImageEffectPluginApi "OfxImageEffectPluginAPI"

and a struct with a const char *pluginApi; where that constant is supposed to be used:

typedef struct OfxPlugin {
  const char *pluginApi;
  // Other fields...
} OfxPlugin;

Bindgen (servo) creates the following Rust equivalent:

pub const kOfxImageEffectPluginApi: &'static [u8; 24usize] = b"OfxImageEffectPluginAPI\x00";
#[repr(C)]
#[derive(Debug, Copy)]
pub struct OfxPlugin {
    pub pluginApi: *const ::std::os::raw::c_char,
    // other fields...
}

What is the best way to get a *const c_char from that const array? I tried both as_ptr and a cast, but the types don't match because the array is u8 and c_char is i8...

Upvotes: 1

Views: 1892

Answers (1)

Matthieu M.
Matthieu M.

Reputation: 299890

Let's start from a minimal example and work our way through:

const K: &'static [u8; 24usize] = b"OfxImageEffectPluginAPI\x00";

#[derive(Debug)]
struct OfxPlugin {
    plugin_api: *const ::std::os::raw::c_char,
    // other fields...
}

fn main() {
    let p = OfxPlugin { plugin_api: K };
    println!("{:?}", p);
}

The first thing to do is to get a pointer from the array; this is indeed as_ptr().

error[E0308]: mismatched types
  --> <anon>:10:41
   |
10 |         let p = OfxPlugin { plugin_api: K.as_ptr() };
   |                                         ^^^^^^^^^^ expected i8, found u8

error: aborting due to previous error

The types mismatch, so we need to cast from one pointer type to another. This is achieved with as:

fn main() {
    let p = OfxPlugin { plugin_api: K.as_ptr() as *const _ };
    println!("{:?}", p);
}

We could be explicit about the kind of pointer we want; but it's simpler here to let the compiler manage it.

Upvotes: 1

Related Questions