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

FFI mechanism to declare a symbol for an array #54450

Open
joshtriplett opened this issue Sep 21, 2018 · 6 comments
Open

FFI mechanism to declare a symbol for an array #54450

joshtriplett opened this issue Sep 21, 2018 · 6 comments
Labels
A-array Area: `[T; N]` A-FFI Area: Foreign function interface (FFI) C-feature-request Category: A feature request, i.e: not implemented / a PR. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@joshtriplett
Copy link
Member

If I have a C declaration

char *symbol = "hello world";

I can declare that symbol in Rust as

extern "C" { pub static symbol: *c_char; }

But if I have a C declaration

char symbol[] = "hello world";

I can't directly declare that in Rust in an immediately usable way. In this case, symbol refers directly to the array of characters; while in C it will "degrade" to a pointer if used in a context that expects a pointer, in Rust a declaration referring to symbol will refer to the characters directly. So, for instance, declaring it as a *c_char will result in a pointer whose numeric value contains the first sizeof::<*c_char>() bytes of "hello world".

Declaring symbol as a [c_char; 0] and then obtaining and using its pointer seems wrong.

I can think of a few useful ways to do this, one more straightforward than the other.

One would be to have a means of defining in an extern "C" block something that gets the value of the address of the symbol, just as if in C I'd written char *symbol_ptr = symbol; and then referenced that from Rust. That seems easy enough to do, modulo bikeshedding over the syntax to do so.

Another would be to define symbol as a C array of unknown length. However, that seems unfortunate to deal with.

The most ideal approach I can think of would be to define symbol as a [c_char; _] (using the elided size syntax from rust-lang/rfcs#2545), and then infer the size from the symbol size:

$ nm --print-size test.o 
0000000000000000 000000000000000c D symbol

I don't know how feasible that would be, but it'd be incredibly convenient.

@joshtriplett joshtriplett changed the title FFI mechanism to declare a sybmol for an array FFI mechanism to declare a symbol for an array Sep 21, 2018
@joshtriplett
Copy link
Member Author

(As a side note, at a minimum Rust could at least check declared sizes of arrays against the size of the symbol they reference, at link time.)

@Mark-Simulacrum
Copy link
Member

I think we probably can't derive the length at link time because we might be dynamically linked. Plus, the array type's size must be known to Rust before linking I think since you can implement for only some array lengths

@solson
Copy link
Member

solson commented Sep 21, 2018

One would be to have a means of defining in an extern "C" block something that gets the value of the address of the symbol, just as if in C I'd written char *symbol_ptr = symbol; and then referenced that from Rust. That seems easy enough to do, modulo bikeshedding over the syntax to do so.

This might be possible as a user-defined macro along the lines of lazy_static, like:

extern_symbol_ptr! {
    pub static ptr symbol: *const c_char;
}

expanding to something like

pub static symbol: *const c_char = {
    extern "C" {
        #[link_name = "symbol"]
        static inner: (); // or some more suitable dummy type
    }
    &inner as *const () as *const c_char
};

EDIT: It required a few changes to clear up warnings and the non-Sync static error, but here's a messy proof of concept: https://play.rust-lang.org/?gist=f67a2476f7743d87225e69ae6efd2910&version=stable&mode=debug&edition=2015

@nagisa
Copy link
Member

nagisa commented Sep 22, 2018

But if I have a C declaration

char symbol[] = "hello world";

This declaration is a sugar for

char symbol[11] = "…".

Declaring char[] in C yields an incomplete type which you can only convert to to a pointer anyway. Ditto in C++.

So the most appropriate way to extern this definition in Rust would be

extern "C" {
    pub static symbol: [c_char; 11];
}

Obviously, there are the cases where the length is unknown, in which case your best bet, I think, is

extern "C" {
    pub static symbol: c_char;
}

and then taking the address of symbol in the user code.

@nagisa
Copy link
Member

nagisa commented Sep 22, 2018

As a side note, at a minimum Rust could at least check declared sizes of arrays against the size of the symbol they reference, at link time.

This is way out of rustc’s control and would require explicit support from the whole toolchain. I doubt anybody will be interested in spending the effort necessary to implement such a feature.

@joshtriplett
Copy link
Member Author

joshtriplett commented Sep 22, 2018 via email

@jonas-schievink jonas-schievink added A-FFI Area: Foreign function interface (FFI) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-feature-request Category: A feature request, i.e: not implemented / a PR. labels Jan 27, 2019
@workingjubilee workingjubilee added the A-array Area: `[T; N]` label Mar 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-array Area: `[T; N]` A-FFI Area: Foreign function interface (FFI) C-feature-request Category: A feature request, i.e: not implemented / a PR. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants