1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
// An `extern "C"` block declares symbols someone else defines. Nim's
// `importc` is the same statement, and both are bound by the C ABI, so the
// two declarations describe one symbol rather than one being a translation of
// the other. This is what a crate that would otherwise reach for `libc` needs.
//
// `libc` itself is not transpiled and should not be: it is 129,594 lines of
// which 54,544 are constants and 7,660 are declarations like these, against
// 121 actual function bodies in the whole crate. Nim reaches the same symbols
// natively, so there is nothing to translate.
//
// The C types must be declared honestly. Nim emits a real C prototype where
// Rust does not, so declaring `strlen` as taking `*const u8` is caught by the
// C compiler rather than silently linking against a different signature.
#[allow(non_camel_case_types)]
type c_char = i8;
#[allow(non_camel_case_types)]
type size_t = usize;
extern "C" {
fn abs(x: i32) -> i32;
fn strlen(s: *const c_char) -> size_t;
fn atoi(s: *const c_char) -> i32;
fn labs(x: i64) -> i64;
}
fn cstr(b: &[u8]) -> *const c_char {
b.as_ptr() as *const c_char
}
fn main() {
unsafe {
println!("{} {} {}", abs(-5), abs(0), abs(7));
println!("{}", labs(-9000000000));
println!("{}", strlen(cstr(b"hello\0")));
println!("{}", strlen(cstr(b"\0")));
println!("{}", atoi(cstr(b"-1234\0")));
println!("{}", atoi(cstr(b"42abc\0")));
}
}
|