2017-09-01 51 views
3

build.rs時間,我生成鏽代碼,隨着參數個數可變調用C函數:如何確定目標平臺不是主機平臺的build_rs時間的c_uint大小?

//build.rs 
fn generate_code(param_name: &str, param_type: &str); 

這產生:

c_func(x, {param_name}); 

其中param_type是任意整數類型。

問題在於「整數促銷」。例如,下面的代碼給出了一個編譯時錯誤,因爲p應該由C調用約定variadics被提升到c_uint和鏽沒有做它含蓄:

use std::os::raw::c_uint; 

extern "C" { 
    fn c_func(x: c_uint, ...); 
} 

fn main() { 
    let x: c_uint = 1; 
    let p: u8 = 2; 
    c_func(x, p); 
} 

促進整數,我需要知道的c_uint在目標平臺上大小整數類型與尺寸< = c_uint轉換爲c_uint(並簽署類型c_int),

也許有某種把戲我可以生成代碼的幫助下做( 像c_func(x, p.promote());),其中promote功能是一些神奇的trait的一部分,促進適當的類型?

+1

爲什麼不只是'c_func(x,p as c_uint)'? – Shepmaster

+0

@Shepmaster因爲p的大小可能會更大,在這種情況下'c_uint'我不需要這個對話,實際上這個對話在這種情況下會產生錯誤。 – user1244932

回答

0

我不相信在構建腳本中有任何訪問這些信息的方法。

哪裏的promote函數是一些神奇的特質,促進適當的類型的一部分?

這聽起來像一個可行的解決方案。根據目標平臺,您可以實現各種類型的特徵:

extern crate libc; 

trait Promote { 
    type Output; 

    fn promote(self) -> Self::Output; 
} 

// This can be made into a macro for all the "easy" cases 
impl Promote for u8 { 
    type Output = libc::c_uint; 

    fn promote(self) -> Self::Output { 
     self as Self::Output 
    } 
} 

#[cfg(target_pointer_width = "32")] 
impl Promote for u64 { 
    type Output = libc::uint64_t; 

    fn promote(self) -> Self::Output { 
     self as Self::Output 
    } 
} 

#[cfg(target_pointer_width = "64")] 
impl Promote for u64 { 
    type Output = libc::c_uint; 

    fn promote(self) -> Self::Output { 
     self as Self::Output 
    } 
} 

extern "C" { 
    fn foo(a: u8, ...); 
} 

fn main() { 
    unsafe { 
     foo(1, 1u8.promote(), 1u64.promote()); 
    } 
} 
+0

這個問題我對'unsigned int'或'c_uint'一無所知,C標準對此沒有任何說明,就像至少有'2^16'這樣的值。根據https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models你的代碼用'#[cfg(target_pointer_width =「64」)]''for u64'可能會截斷結果,刪除高32位值或以正確的方式工作。 – user1244932