Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why bindgen interpret wchar_t type as ::std::os::raw::c_int? #1745

Closed
Al-Rozhkov opened this issue Mar 10, 2020 · 4 comments
Closed

Why bindgen interpret wchar_t type as ::std::os::raw::c_int? #1745

Al-Rozhkov opened this issue Mar 10, 2020 · 4 comments

Comments

@Al-Rozhkov
Copy link

This is a question.

I have compiled dynamic C library, a header file for it and a documentation. I successfully built bindings with bindgen. I got pub type wchar_t = ::std::os::raw::c_int; in my bindings.rs. But looks like C function must accept wchar_t as string.

Input C Header

#define SETTING_KEY L"OfdChannel"

DTOX_SHARED_EXPORT void DTOX_SHARED_CCA ffi_set_single_setting(lib_handle handle, const wchar_t *key, const wchar_t *value);

bindings.rs

pub const SETTING_KEY: &'static [u8; 11usize] = b"OfdChannel\0";
pub type wchar_t = ::std::os::raw::c_int;

extern "C" {
    pub fn ffi_set_single_setting(
        handle: libfptr_handle,
        key: *const wchar_t,
        value: *const wchar_t,
    );
}

I'm struggling to create safe wrapper around this functions because key const has type [u8] but the function expects i32 (c_int) as argument.

Here is my wrapper:

pub fn set_single_setting(&self) {
  let raw_key: *const _ = &SETTING_KEY;
  let value = 2;
  let raw_value: *const i32 = &value;
  unsafe {
    ffi_set_single_setting(self.handle, raw_key, raw_value);
    ffi_apply_single_settings(self.handle);
  }
}

It doesn't compile: raw_key expected to be i32, found &[u8; 11].

What am I doing wrong? Any help would be appreciated.

@emilio
Copy link
Contributor

emilio commented Mar 11, 2020

You're not doing anything wrong, as far as I can tell. The bug is not in the function signature, but in the constant definition, that should ideally be a wide char array.

I took a look, and cexpr doesn't give any hint that we could use to distinguish. So this is a problem in there.

I filed #1745, closing as a dupe of that.

@emilio emilio closed this as completed Mar 11, 2020
@Al-Rozhkov
Copy link
Author

@emilio thank you!

You posted link to exact this issue. Should be jethrogb/rust-cexpr#25 (Allow to distinguish wide strings from regular strings) I guess.

@emilio
Copy link
Contributor

emilio commented Mar 11, 2020

Err, whoops, indeed :)

@emilio
Copy link
Contributor

emilio commented Mar 11, 2020

In the meantime, though ugly (and assuming the key won't change), you can do something like:

const KEY: [wchar_t; 11] = [b'O' as wchar_t, ..., b'\0' as wchar_t];
unsafe {
    ffi_set_single_setting(self.handle, KEY.as_ptr(), ...);
}

Or if you're in control of the C headers you can do something like:

extern const wchar_t BINDGEN_SETTING_KEY[] = SETTING_KEY;

And you should be able to use the BINDGEN_ version and it should have the right type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants