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