|
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