2016-11-04 36 views
5

mexPrintf, printf gibi, bir varargs argüman listesi kabul eder. Bunu Rust'ta sarmanın en iyi yolunun ne olduğunu bilmiyorum. RFC for variadic generics var, ama bugün ne yapabiliriz?Çağrı, Rust'ta VarArgs kullanan bir FFI işlevine nasıl sarılır?

Bu örnekte, giriş ve çıkışların sayısını yazdırmak istiyorum, ancak sarılmış işlev yalnızca çöpleri yazdırıyor. Bunu düzeltmek için bir fikrin var mı?

enter image description here

#![allow(non_snake_case)] 
    #![allow(unused_variables)] 

extern crate mex_sys; 

use mex_sys::mxArray; 
use std::ffi::CString; 
use ::std::os::raw::c_int; 
use ::std::os::raw::c_void; 

type VarArgs = *mut c_void; 

// attempt to wrap mex_sys::mexPrintf 
fn mexPrintf(fmt: &str, args: VarArgs) { 
    let cs = CString::new(fmt).unwrap(); 
    unsafe { 
     mex_sys::mexPrintf(cs.as_ptr(), args); 
    } 
} 

#[no_mangle] 
pub extern "system" fn mexFunction(nlhs: c_int, 
            plhs: *mut *mut mxArray, 
            nrhs: c_int, 
            prhs: *mut *mut mxArray) { 

    let hw = CString::new("hello world\n").unwrap(); 
    unsafe { 
     mex_sys::mexPrintf(hw.as_ptr()); 
    } 

    let inout = CString::new("%d inputs and %d outputs\n").unwrap(); 
    unsafe { 
     mex_sys::mexPrintf(inout.as_ptr(), nrhs, nlhs); 
    } 

    mexPrintf("hello world wrapped\n", std::ptr::null_mut()); 

    let n = Box::new(nrhs); 
    let p = Box::into_raw(n); 
    mexPrintf("inputs %d\n", p as VarArgs); 

    let mut v = vec![3]; 
    mexPrintf("vec %d\n", v.as_mut_ptr() as VarArgs); 
} 

Güncelleme: Ben va_list ile variable list of arguments karıştı almıştı. Her ikisinden de kaçınacağım ve eğer bu durumda, Rust'u dizgiye dönüştürmeden önce dizgeyi formatlamak istiyorum. İşte bu durumda benim için çalıştı budur:

#![allow(non_snake_case)] 
#![allow(unused_variables)] 

extern crate mex_sys; 

use mex_sys::mxArray; 
use std::ffi::CString; 
use ::std::os::raw::c_int; 

// attempt to wrap mex_sys::mexPrintf 
fn mexPrintf(text: &str) { 
    let cs = CString::new(text).expect("Invalid text"); 
    unsafe { mex_sys::mexPrintf(cs.as_ptr()); } 
} 

#[no_mangle] 
pub extern "C" fn mexFunction(nlhs: c_int, plhs: *mut *mut mxArray, nrhs: c_int, prhs: *mut *mut mxArray){ 
    mexPrintf(&format!("{} inputs and {} outputs\n", nrhs, nlhs)); 
} 
Sanılanın aksine

enter image description here

+3

mexPrintf, "printf" veya "va_list" gibi "vprintf" gibi değişken sayıda bağımsız değişken kabul ediyor mu? Birincisi, tamsayıya bir işaretçi olarak değil, doğrudan geçmeniz gerekiyorsa. –

+0

Teşekkürler @ChrisEmerson, ne yazık ki iki kafası karıştı. Bunu temizlemeye yardım ettiğiniz için teşekkürler. –

cevap

4

, bu anlamına gelmez O C. tanımlandı çağrı variadic/vararg fonksiyonları mümkündür Bunu yapmak çok kolay ve kötü bir şey yapmak kesinlikle daha kolay çünkü derleyicinin çalışmanızı kontrol etmesi için daha az sayıda türü var.

printf numaralı telefonu arayın. Sadece her şeyi kodlanmış ettik: Çok açıkça benim biçim dizesi ve argümanlar tamam türleridir ve dizeleri boş karakter sonlandırmalı olduğundan emin olmak zorunda

extern crate libc; 

fn my_thing() { 
    unsafe { 
     libc::printf(b"Hello, %s (%d)\0".as_ptr() as *const i8, b"world\0".as_ptr(), 42i32); 
    } 
} 

fn main() { 
    my_thing() 
} 

Not.

Normalde, CString gibi araçları kullanırız:

extern crate libc; 

use std::ffi::CString; 

fn my_thing(name: &str, number: i32) { 
    let fmt = CString::new("Hello, %s (%d)").expect("Invalid format string"); 
    let name = CString::new(name).expect("Invalid name"); 

    unsafe { 
     libc::printf(fmt.as_ptr(), name.as_ptr(), number); 
    } 
} 

fn main() { 
    my_thing("world", 42) 
} 

Pas derleyici test paketi de an example of calling a variadic function sahiptir.


printf benzeri işlevler için özel olarak uyarı bir kelime: C derleyicisi-yazarlar insanların variadic işlev çağrısı her zaman bu özel tip berbat olduğunu fark etti. Bununla mücadele etmek için, biçim dizesini ayrıştıran özel bir mantığı kodladılar ve argüman türlerini biçim dizisinin beklediği türlere göre kontrol etmeye çalışırlar. Rust derleyici sizin için C tarzı biçim dizelerinizi kontrol etmeyecektir!