|
8 | 8 | // option. This file may not be copied, modified, or distributed |
9 | 9 | // except according to those terms. |
10 | 10 |
|
11 | | -// ignore-msvc -- sprintf isn't a symbol in msvcrt? maybe a #define? |
12 | | - |
13 | | -#![feature(libc, std_misc)] |
14 | | - |
15 | | -extern crate libc; |
16 | | - |
17 | | -use std::ffi::{CStr, CString}; |
18 | | -use libc::{c_char, c_int}; |
19 | | - |
20 | | - |
| 11 | +#[link(name = "rust_test_helpers")] |
21 | 12 | extern { |
22 | | - fn sprintf(s: *mut c_char, format: *const c_char, ...) -> c_int; |
23 | | -} |
24 | | - |
25 | | -unsafe fn check<T, F>(expected: &str, f: F) where F: FnOnce(*mut c_char) -> T { |
26 | | - let mut x = [0 as c_char; 50]; |
27 | | - f(&mut x[0] as *mut c_char); |
28 | | - assert_eq!(expected.as_bytes(), CStr::from_ptr(x.as_ptr()).to_bytes()); |
| 13 | + fn rust_interesting_average(_: u64, ...) -> f64; |
29 | 14 | } |
30 | 15 |
|
31 | 16 | pub fn main() { |
32 | | - |
| 17 | + // Call without variadic arguments |
33 | 18 | unsafe { |
34 | | - // Call with just the named parameter |
35 | | - let c = CString::new(&b"Hello World\n"[..]).unwrap(); |
36 | | - check("Hello World\n", |s| sprintf(s, c.as_ptr())); |
37 | | - |
38 | | - // Call with variable number of arguments |
39 | | - let c = CString::new(&b"%d %f %c %s\n"[..]).unwrap(); |
40 | | - check("42 42.500000 a %d %f %c %s\n\n", |s| { |
41 | | - sprintf(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr()); |
42 | | - }); |
| 19 | + assert!(rust_interesting_average(0).is_nan()); |
| 20 | + } |
43 | 21 |
|
44 | | - // Make a function pointer |
45 | | - let x: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int = sprintf; |
| 22 | + // Call with direct arguments |
| 23 | + unsafe { |
| 24 | + assert_eq!(rust_interesting_average(1, 10i64, 10.0f64) as i64, 20); |
| 25 | + } |
46 | 26 |
|
47 | | - // A function that takes a function pointer |
48 | | - unsafe fn call(fp: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int) { |
49 | | - // Call with just the named parameter |
50 | | - let c = CString::new(&b"Hello World\n"[..]).unwrap(); |
51 | | - check("Hello World\n", |s| fp(s, c.as_ptr())); |
| 27 | + // Call with named arguments, variable number of them |
| 28 | + let (x1, x2, x3, x4) = (10i64, 10.0f64, 20i64, 20.0f64); |
| 29 | + unsafe { |
| 30 | + assert_eq!(rust_interesting_average(2, x1, x2, x3, x4) as i64, 30); |
| 31 | + } |
52 | 32 |
|
53 | | - // Call with variable number of arguments |
54 | | - let c = CString::new(&b"%d %f %c %s\n"[..]).unwrap(); |
55 | | - check("42 42.500000 a %d %f %c %s\n\n", |s| { |
56 | | - fp(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr()); |
57 | | - }); |
58 | | - } |
| 33 | + // A function that takes a function pointer |
| 34 | + unsafe fn call(fp: unsafe extern fn(u64, ...) -> f64) { |
| 35 | + let (x1, x2, x3, x4) = (10i64, 10.0f64, 20i64, 20.0f64); |
| 36 | + assert_eq!(fp(2, x1, x2, x3, x4) as i64, 30); |
| 37 | + } |
59 | 38 |
|
60 | | - // Pass sprintf directly |
61 | | - call(sprintf); |
| 39 | + unsafe { |
| 40 | + call(rust_interesting_average); |
62 | 41 |
|
63 | | - // Pass sprintf indirectly |
| 42 | + // Make a function pointer, pass indirectly |
| 43 | + let x: unsafe extern fn(u64, ...) -> f64 = rust_interesting_average; |
64 | 44 | call(x); |
65 | 45 | } |
66 | | - |
67 | 46 | } |
0 commit comments