2016-11-04 15 views
5

mexPrintfは、printfのように、引数の可変リストを受け入れます。私は、これをラストで包む最良の方法が何かを知りません。 RFC for variadic genericsがありますが、今日は何ができますか?RustでVarArgsを使用するFFI関数に呼び出しをラップする方法は?

この例では、入力と出力の数を出力したいが、ラップされた関数は単にガベージを出力します。どのようにこれを修正するための任意のアイデア?

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

アップデート:私はva_listvariable list of argumentsを混同していました。私はこの状況で両方を避けるつもりですが、私はちょうどそれをinteropに渡す前にRustで文字列フォーマットを行うつもりです。ここでは、この場合には私のために働いていたものです:

人気の信念に反して
#![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)); 
} 

enter image description here

+3

mexPrintfは、 'printf'や' vprint_'のような 'va_list'のような可変数の引数を受け入れることを意味しますか?前者の場合は、整数へのポインタではなく直接渡す必要があります。 –

+0

ありがとう@ChrisEmerson、私は悲しげに2つを混乱させる。それをクリアするのを助けてくれてありがとう。 –

答えて

4

、それがあることを意味するものではありませんCで定義されていたコール可変引数/可変引数機能することが可能ですそうすることは非常に簡単で、コンパイラが作業をチェックするタイプがより少なくなるため、何か悪いことを行う方がはるかに簡単です。

ここにはprintfを呼び出す例があります。私はちょうどすべてについて、ハードコードされました:私は非常に明示的に私の書式文字列と引数はすべて右のタイプで、文字列はNUL終端されていることを確認する必要があり

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() 
} 

注意を。

通常は、CStringのようなツールを使用します:

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

錆コンパイラのテストスイートもan example of calling a variadic functionを持っています。


printf様な機能のために特別に警告の言葉:Cコンパイラ-作家は、人々はすべての時間可変引数関数呼び出しのこの特定のタイプを台無しにすることを実現しました。これに対処するために、彼らはフォーマット文字列を解析して、フォーマット文字列が期待する型に対して引数型をチェックしようとする特別なロジックをエンコードしています。 RustコンパイラはCスタイルの書式文字列をチェックしません!

関連する問題