Reputation: 33
This is short example about this question.
#[fixed_stack_segment]
fn test(func: extern "C" fn() -> ~str) -> ~str {
func()
}
extern "C" fn func1() -> ~str {
~"hello"
}
fn main() {
let func2 = || -> ~str { ~"world" };
println(test(func1));
println(test(func2));
}
Then, rustc stops with error.
st.rs:13:17: 13:22 error: mismatched types: expected `extern "C" fn() -> ~str` but found `&fn<no-bounds>() -> ~str` (expected extern fn but found fn)
st.rs:13 println(test(func2));
I cannot find a way to make the lambda be an extern fn.
What should I do?
Upvotes: 3
Views: 3318
Reputation: 102066
The closure syntax is always either &fn
or ~fn
, and to make an extern "ABI" fn
(for any value of ABI
, including Rust
), one needs to use a full function declaration.
#[fixed_stack_segment]
fn test(func: extern "C" fn() -> ~str) -> ~str {
func()
}
extern "C" fn func1() -> ~str {
~"hello"
}
fn main() {
extern "C" fn func2() -> ~str { ~"world" }
println(test(func1));
println(test(func2));
}
There is some talk of allowing lambdas to create non-closures too, with the ABI inferred like anything else in a type signature, but this isn't implemented yet.
However, as Vladimir Matveev says, there is a fundamental difference between closures and normal functions, which means that one will never be able to use all the features of closures when passed as an extern fn
. The difference is closures can capture (references to) variables, i.e.
let n = 1;
let f = || { n + 1 };
This means a closure is effectively represented by
struct AndFn { // &fn
env: &Environment,
func: extern "Rust" fn()
}
struct TwiddleFn { // ~fn
env: ~Environment,
func: extern "Rust" fn()
}
where Environment
is a struct that contains all the capture variables for that closure (it differs for each &fn
, since each one captures different things); the func
is a function pointer to the code of the closure, which is what gets executed when the closure is called; if a closure captures any variables, the func
will require the env
to exist. Thus, the lambda syntax will only be able to create plain extern fn
s when it captures no variables.
Upvotes: 4