I am attempting to write a simple api with rocket to help myself learn rust but I have run into this error after I attempted declaring a POST route:
error: malformed attribute
--> src/main.rs:26:1
|
26 | #[post("/producers", format="application/json", data =<"prod">)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: expected syntax: #[post(key = value, ..)]
Here is the function declaration for that route:
#[post("/producers", format="application/json", data =<"producer">)]
fn post_producer(producer: Json<Producer>) -> String {
return("hello".to_string());
}
And I am importing these macros:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use] extern crate rocket;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate rocket_contrib;
use rocket_contrib::json::Json;
I have another method declared for GET but that one works fine. I've done some research and found these examples and documentation:
https://api.rocket.rs/v0.4/rocket_codegen/attr.post.html
https://rocket.rs/v0.4/guide/requests/#format
As far as I can tell I am following the conventions mentioned in both of those pages and I'm a bit lost on where to go from here. Is there some bit of syntax or an import that I'm missing?
According to the documentation, the data parameter must have the <> inside of the quotation marks. So data="<prod>" should fix the issue.
Related
What I'd like to do:
#[wasm_bindgen]
pub type ParseError = parserange::Error;
But the Rust compiler complains:
error: #[wasm_bindgen] can only be applied to a function, struct, enum, impl, or extern block
--> src/lib.rs:89:1
|
89 | pub type ParseError = parserange::Error;
I don't want to add the #[wasm-bindgen] attribute in parserange.rs because it's in a separate library that doesn't build with wasm.
Is there a work-around?
The workaround is to wrap the parserange::Error in a tuple struct to create a new type. The downside of this is that all functions defined on parserange::Error that you'd like to use will have to be redefined to call the error sub-object's function. This has all the advantages of creating a new type though, such as exporting in through wasm_bindgen, or implementing traits on a type defined in another crate. More information can be found here
Using the below code in main.rs, when I run cargo test it returns error code 176, when I add a test or `any statement in main function. It starts returning error code 160.
#![no_std]
#![no_main]
#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(not(test))]
extern crate panic_halt;
#[no_mangle]
pub unsafe extern "C" fn main() {
}
From this link I found out, that
Exit code 176 means "Unable to install on a network drive. Select
another install location in your preferences and retry installing."
When I tried to find back trace through lldb it returned
error: invalid thread
I couldn't find any thread which mentions similar error, so asking it here.
Any help is appreciated.
Using nightly (nightly-x86_64-apple-darwin)
Thanks.
The problem is your main function, which has an invalid signature for unix platforms. It must return an i32 (or better c_int, but for simplicity we suppose they are idential).
The 176 is just some random value in the rax register when leaving the main function.
So change your main signature to:
pub unsafe extern "C" fn main() -> i32
and return a return code (e.g. 0 which means success)
or
pub unsafe extern "C" fn main() -> !
and use the exit syscall on linux (or an infinite loop on embedded systems).
I'm trying to get my head around function-like procedural macros and struggling with the basics.
For a starter, I tried to create a macro that just prints all the tokens and does nothing:
extern crate proc_macro;
extern crate syn;
use proc_macro::TokenStream;
#[proc_macro]
pub fn my_macro(input: TokenStream) -> TokenStream {
println!( "{:?}", input );
TokenStream::new()
}
I then tried to use it in another binary:
extern crate rust_procmacro_test;
fn main() {
rust_procmacro_test::my_macro!( aaa );
}
When I do cargo build I get this:
Compiling rust_procmacro_test v0.1.0
Compiling procmacro_user v0.1.0
error[E0658]: procedural macros cannot be expanded to statements (see issue #54727)
--> src\main.rs:5:5
|
5 | rust_procmacro_test::my_macro!( aaa );
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TokenStream [Ident { ident: "aaa", span: #0 bytes(114..117) }]
error: aborting due to previous error
It tells me that this cannot be compiled, but println inside the macro works. What is happening?
Issue #54727 is very broad and I'm not sure how it relates to this.
I'm using stable-i686-pc-windows-gnu, rustc 1.31.1 (b6c32da9b 2018-12-18).
What is happening?
While it's possible to define a function-like procedural macro in stable Rust, it's not yet possible to call one as an expression / statement. This is because there are concerns about how hygiene should be applied. There are other locations, such as in item position, where it is available:
extern crate rust_procmacro_test;
rust_procmacro_test::my_macro!( aaa );
fn main() {}
but println inside the macro works
This is probably just some laziness in the implementation — the macro is eagerly evaluated and then the feature gate is checked later. While this might be inefficient at the moment, once the feature is fully stabilized it won't matter.
EDIT: It was pointed out that my example isn't complete enough to be useful. My question is resolved, but if you're interested in looking at the complete code you can see it here.
Given the following code:
#[no_mangle]
pub extern "C" fn create_acceptor() -> Acceptor {
Acceptor {}
}
pub struct Acceptor {}
If I call this from C what does it actually get? Is it a pointer? An id of some sort?
I'm currently using code like the following on the C side:
extern int create_acceptor();
int main(int argc, char **argv) {
int acceptor = create_acceptor();
return 0;
}
It seems to work fine. I'm using it like an opaque type that I pass back to Rust like acceptor_doSomething(acceptor).
But I'm confused because it doesn't seem to matter what type I use for acceptor on the C side. void* and int both behave the same. Also, the documentation seems to indicate that I should be using #[repr(C)], but it seems to work without it. Why is that?
When printing the value received on the C side, it's showing very small integers, so I'm guessing it's an id on the Rust side?
TL;DR: The example isn't a useful one and doesn't show anything.
what does it actually get? Is it a pointer? An id of some sort?
It's the struct, exactly as defined on the Rust side. It's a pointer if you return a pointer (this example does not) or an id if you return some id (this example does not).
Rust's FFI imposes no overhead or abstraction — what you return is what is returned.
the documentation seems to indicate that I should be using #[repr(C)]
Yes, you should. Without it, your code is most likely undefined behavior. The layout of a Rust struct is not yet guaranteed. Without specifying the representation as C, there's no way for the C code to know which fields are where.
but it seems to work without it
That's because your example struct has no fields and thus no size (which AFAIK isn't even valid in C without non-standard extensions). Rust basically never even needs to look at the data (what data?) so it doesn't matter what you pass back.
When printing the value received on the C side, it's showing very small integers
This is probably just junk on the stack laying around. Literally uninitialized data.
Using a struct with fields without #[repr(C)]
This is bad. Don't do it. String is a struct with non-trivial fields and it is not marked #[repr(C)].
Cargo.toml
[package]
name = "shear"
version = "0.1.0"
authors = ["An Devloper"]
[lib]
crate-type = ["cdylib"]
[dependencies]
src/lib.rs
// Don't do this, `String` isn't #[repr(C)]!
#[no_mangle]
pub extern "C" fn create_example() -> String {
String::from("hello")
}
// Don't do this, `String` isn't #[repr(C)]!
#[no_mangle]
pub extern "C" fn use_example(e: String) {
println!("{}", e);
}
main.c
extern int create_example();
extern void use_example(int example);
int main(int argc, char **argv) {
int example = create_example();
use_example(example);
}
Execution
$ cargo build
Compiling shear v0.1.0 (file:///home/ubuntu/shear)
Finished dev [unoptimized + debuginfo] target(s) in 1.02s
$ gcc -o example main.c -L target/debug/ -lshear
$ LD_LIBRARY_PATH=target/debug/ ./example
Segmentation fault
Please read the The Rust FFI Omnibus for details about how to properly transfer values across the FFI boundary. Disclaimer: I am the primary author.
Consider the following contrived situation:
mod imported {
pub trait Imported {
fn hello(&self, x:int) -> int;
}
}
struct Hi;
impl imported::Imported for Hi {
fn hello(&self, x:int) -> int {
return x;
}
}
#[test]
fn test_thing() {
let value = Hi;
println!("{:?}", value.hello(10));
}
This won't compile, because the trait Imported is not in scope, so the method hello() cannot be invoked:
imports.rs:20:18: 20:33 error: type `imports::Hi` does not implement any method in scope named `hello`
imports.rs:20 println!("{:?}", value.hello(10));
^~~~~~~~~~~~~~~
If we put Imported in the current scope (ie. get rid of mod imported) this works fine, but like this, it does not.
Normally for this purpose you would use 'use' to bring the 'Imported' symbol into the local scope:
use imported::Imported;
However, in this case you cannot, because the symbol 'imported' does not yet exist at the beginning of the file:
imports.rs:2:5: 2:13 error: unresolved import. maybe a missing `extern crate imported`?
imports.rs:2 use imported::Imported;
^~~~~~~~
imports.rs:2:5: 2:23 error: failed to resolve import `imported::Imported`
imports.rs:2 use imported::Imported;
^~~~~~~~~~~~~~~~~~
And you cannot do it after the mod imported call, because:
imports.rs:8:1: 8:24 error: `use` and `extern crate` declarations must precede items
imports.rs:8 use imported::Imported;
^~~~~~~~~~~~~~~~~~~~~~~
To be fair this only occurs when you are implementing a trait and then trying to use that impl in the safe file, but it seems like this would actually be quite a common use case for testing.
You can work around it by structuring your code slightly differently and importing modules from some common parent, but this seems like an inherent limitation of the current system.
Am I missing something?
I think you have indeed missed something. Adding use imported::Imported; at the top of the file does work—I presume that this is not precisely what you tried to compile.
use statements, although written before the mod statements, are resolved after the mod, so there is no source order problem.
I presume that your error is in fact that your file imports.rs was not the crate root. Remember that a use statement takes an absolute path if you don't use super or self in it. To make it work in any place, you would need to write use self::imported::Imported;; assuming you were compiling a lib.rs containing mod imports;, you would have needed to use imports::imported::Imported, the absolute path to the trait.
(BTW, you can replace return x; at the end of the function with just x. Remember Rust's block value doctrine, whereby the last expression in a block is the value of the block.)