Skip to content

Support standard C numeric types #874

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

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

adetaylor
Copy link
Collaborator

This adds direct support for the C integer and float types
defined in std::os::raw. Unlike existing cxx-supported integers,
these may not be a consistent length on all platforms - but sometimes
this is useful to enable direct interoperability with existing
APIs.

adetaylor added 2 commits May 11, 2021 20:24
This adds direct support for the C integer and float types
defined in std::os::raw. Unlike existing cxx-supported integers,
these may not be a consistent length on all platforms - but sometimes
this is useful to enable direct interoperability with existing
APIs.
Copy link
Owner

@dtolnay dtolnay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is great.

However I am slightly hesitant to land this without having #682 because it breaks code like:

#[cxx::bridge]
mod ffi {
    extern "C++" {
        include!("header.h");  // `using c_int = int;`

        type c_int;
    }

    extern "Rust" {
        fn f(v: &CxxVector<c_int>);
    }
}

Maybe it would turn out fine for this specific set of names. Let me think about it.

Would you be able to look into whether there is an easy implementation of #682 that would prevent this PR from breaking previously working code?

@adetaylor
Copy link
Collaborator Author

Yep, I'll take a look.

Floats are always 32-bit and doubles always 64-bit, so there's
no need to duplicate the existing f32 and f64 support.
@adetaylor
Copy link
Collaborator Author

I added a design sketch to #682 - please take a look. It looks OK, but non-trivial, so unlikely I'll get to it especially soon. Maybe though.

@thevurv
Copy link

thevurv commented Nov 8, 2021

Status on this?

@nathan-at-least
Copy link

Hi,

Prior to, or in addition to, this PR landing, is there a way to improve the docs with guidance on how to handle numeric types? Besides this table, I can't find any guidance aside from this terse sentence:

In addition to all the primitive types (i32 <=> int32_t), …

What about u8 vs char? What is c_char which seems to be in scope in the extern "Rust" section and where does that come from?

This may be something people with c++ backgrounds would know, but in c++ is std::int32_t always the same as int?

My background:

  • I'm reasonably familiar with rust, whereas my c++ expertise is quite weak.
  • I don't have experience with rust <-> c ffi bindings. I've read over A little C with your Rust, Rustonomicon FFI, and skimmed the libc API docs.
  • Little experience with no_std and core (aside from some wasm guest code experiments).

My journey: (This part is a longer narrative and hopefully useful to people thinking about improving docs.)

I want to write a rust function to parse commandline options and a config file given the int argc, char *argv[] from c++'s main.

Inside the extern "Rust" I try out this interface: fn parse_cli_and_config(argc: c_int, argv: *const *const c_char) where c_int and c_char are from use std::ffi::{c_int, c_char} in the top body (prior to #[cxx::bridge]).

This gives a cxx procmacro error (I assume) for unsupported type:

175 │         unsafe fn parse_args_and_file(argc: c_int, argv: *const *const c_char) -> Result<Config>;
    │                                             ^^^^^ unsupported type

Fair enough.

Ok, so I remove the use std::ffi::… and I begin to replace the rust imported types. Hopefully c++ int is always i32. (I'm not certain, which is why I prefer to rely on the abstract from std::ffi.)

But wait, building now works, even though I didn't replace c_char with u8! How does that work? It isn't mentioned in the cxx API docs, AFAICT, and I am not brinding that type into scope with use. So is this somehow an implicitly defined type by cxx bridge or does it come from somewhere else?

So as it stands, I'm somewhat mystified about the primitive numeric types and which types are in scope within the #[cxx::bridge].

BTW- if this PR lands, and I could simply use the std::ffi::c_* types, the docs should also mention relying on those types if that's the recommended pattern.

@Starosielec
Copy link

But wait, building now works, even though I didn't replace c_char with u8! How does that work?

I also frequently see failing code going through partial builds sometimes. there seems to be some minor caching problems with partial builds. Try cargo clean and retry, “c_char” should fail.

@kaz-49
Copy link

kaz-49 commented Jan 2, 2025

Hello. It looks like this thread's been stale for over a year now, may I know how it's going?

@PeterWang-dev
Copy link

What is the status is current project? Because of this, cxx now is not usable in my project.

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

Successfully merging this pull request may close these issues.

7 participants