2013-10-15 35 views
2

這是關於此問題的簡短示例。如何使關閉類型'extern「C」fn「

#[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)); 
} 

然後,rustc停止並出錯。

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)); 

我找不到讓lambda成爲extern fn的方法。

我該怎麼辦?

+2

我不認爲你可以,因爲閉包意味着捕獲環境,而外部函數沒有任何環境。但我不確定,讓我們等待更權威的答案。 –

回答

2

封閉語法始終爲&fn~fn,和作出extern "ABI" fn(對於ABI任何值,包括Rust),需要使用完整的函數聲明。

#[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)); 
} 

有允許lambda表達式創建非封閉過,與ABI推斷像在類型簽名別的的一些談話,但是這還沒有實現。


然而,正如弗拉基米爾Matveev說,有封鎖和正常功能之間有着根本的區別,這意味着當爲extern fn通過一個永遠無法使用關閉的所有功能。所不同的是封閉件可以捕捉(引用)的變量,即

let n = 1; 
let f = || { n + 1 }; 

這意味着封閉被有效地

struct AndFn { // &fn 
    env: &Environment, 
    func: extern "Rust" fn() 
} 

struct TwiddleFn { // ~fn 
    env: ~Environment, 
    func: extern "Rust" fn() 
} 

表示,其中Environment是包含所有該閉合捕獲變量一個結構(它因每個&fn而不同,因爲每一個捕獲不同的東西); func是一個函數指針,指向閉包的代碼,當閉包被調用時它被執行;如果閉包捕獲任何變量,func將需要env存在。因此,lambda語法只能捕獲沒有變量時才能創建簡單的extern fn

+0

嗯...,我試着用[rust-mozjs](https://github.com/mozilla-servo/rust-mozjs)並且想要包裝JSFuntionSpec(它需要'extern「C」fn')。 謝謝!我會尋找其他方式。 –