Skip to content

Bindgen converts char to c_schar instead of c_char #603

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

Closed
crumblingstatue opened this issue Mar 28, 2017 · 10 comments
Closed

Bindgen converts char to c_schar instead of c_char #603

crumblingstatue opened this issue Mar 28, 2017 · 10 comments

Comments

@crumblingstatue
Copy link

Input C/C++ Header

struct foo {
	char member;
};

Bindgen Invokation

bindgen foo.h

Actual Results

/* automatically generated by rust-bindgen */

#[repr(C)]
#[derive(Debug, Copy)]
pub struct foo {
    pub member: ::std::os::raw::c_schar,
}
#[test]
fn bindgen_test_layout_foo() {
    assert_eq!(::std::mem::size_of::<foo>() , 1usize , concat ! (
               "Size of: " , stringify ! ( foo ) ));
    assert_eq! (::std::mem::align_of::<foo>() , 1usize , concat ! (
                "Alignment of " , stringify ! ( foo ) ));
    assert_eq! (unsafe {
                & ( * ( 0 as * const foo ) ) . member as * const _ as usize }
                , 0usize , concat ! (
                "Alignment of field: " , stringify ! ( foo ) , "::" ,
                stringify ! ( member ) ));
}
impl Clone for foo {
    fn clone(&self) -> Self { *self }
}

Expected Results

The field should be c_char, not c_schar. char is not defined as always signed in the C standard. It can be unsigned.

@crumblingstatue
Copy link
Author

From a short investigation, it seems that bindgen only knows about char, which maps to c_schar, and unsigned char, which maps to c_uchar. But there are 3 types.

| C             | Rust    |
+---------------+---------+
| char          | c_char  |
| signed char   | c_schar |
| unsigned char | c_uchar |

@emilio
Copy link
Contributor

emilio commented Mar 28, 2017

The field should be c_char, not c_schar. char is not defined as always signed in the C standard. It can be unsigned.

Right, but LLVM takes care of figuring out signedness for us. See #559.

@crumblingstatue
Copy link
Author

crumblingstatue commented Mar 29, 2017

Right, but LLVM takes care of figuring out signedness for us. See #559.

Maybe so when bindgen is used as part of the build process for the target platform, but this doesn't work when generating one set of bindings that's meant to be used on all platforms, using the command line application.

Or is this mode of operation now unsupported?

  1. Generating a different binding for every target platform would be tedious and repetitive, but this is the more viable option for me, because:

  2. Using bindgen as part of the build process has several problems:

    • It requires that everyone who wants to build my crate has Clang.
    • It results in an enormous blowup in compile times for my crate, because bindgen has to be compiled.
    • The bindgen output by itself is unusable because of several issues, most notably Option for only generating bindings for filenames matching a pattern #303. I have to edit the generated bindings for it to be usable. This would mean I would have to write software to manipulate the bindgen output instead of doing the editing manually.

crumblingstatue added a commit to jeremyletang/rust-sfml that referenced this issue Mar 29, 2017
@emilio
Copy link
Contributor

emilio commented Mar 29, 2017

Or is this mode of operation now unsupported?

I guess that has only ever worked because of the platforms people generate bindings in happen to have signed chars.

I guess this would need a bit of a hack to work, but I believe it can be done.

In particular, we could try to check the type spelling to see if it doesn't contain neither signed or unsigned, and use that... Assuming the spelling clang gives us is the proper one.

@dimbleby
Copy link
Contributor

dimbleby commented Apr 3, 2017

I guess that has only ever worked because of the platforms people generate bindings in happen to have signed chars.

The reason this "ever worked" is that it had only been broken for three weeks when reported (4f1e3da).

I'm completely in agreement with what @crumblingstatue says about wanting to generate bindings offline. So "me too" on this one.

@emilio
Copy link
Contributor

emilio commented Apr 3, 2017

The reason this "ever worked" is that it had only been broken for three weeks when reported (4f1e3da).

The point is that before that change, we used char when libclang reported a signed char.

@dimbleby
Copy link
Contributor

dimbleby commented Apr 3, 2017

Yes, I understand. But I guess that it's much more common for C APIs to use char than it is explicitly to use signed char - at any rate, that's true in the case of the API that I care about.

So I expect we've switched from "uncommon case is broken" to "common case is broken".

@dimbleby
Copy link
Contributor

dimbleby commented Apr 3, 2017

It looks easy enough to 90% fix this, by which I mean convert types correctly from C to Rust. But there are still some places where bindgen asks whether a type is signed, and it's obviously impossible to give a universal definitive answer for char.

Let me put together a pull request...

dimbleby added a commit to dimbleby/rust-c-ares that referenced this issue Apr 3, 2017
bors-servo pushed a commit that referenced this issue Apr 3, 2017
ir: Handle char in a more cross-platform way when possible.

This should address #603, and supersede #609
bors-servo pushed a commit that referenced this issue Apr 4, 2017
Treat char as c_char

Per #603.

This still leaves `bindgen` having to make a call as to what to say when asked whether `Char` `is_signed()`.  I've opted just to leave this as `true`, on the grounds that:

* I don't currently understand an example where it matters
* I suspect that if there are cases where it matters, then it shouldn't!
  * Because by definition, use of unadorned `char` in the original header says that it doesn't care about signedness
* (signed is the common case, so that's a more sensible guess than unsigned)
@fitzgen
Copy link
Member

fitzgen commented Apr 5, 2017

@emilio @dimbleby @crumblingstatue Can this issue be closed now?

@emilio
Copy link
Contributor

emilio commented Apr 6, 2017

I think so, yes.

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

4 participants