#![allow(clippy::multiple_unsafe_ops_per_block)]
use std::ffi::{CStr, c_char, c_int, c_long};
use dlsym::{Bindings, Library};
dlsym::library! {
pub struct LibC {
unsafe extern "C" {
pub safe fn labs(x: c_long) -> c_long;
pub fn strlen(s: *const c_char) -> usize;
pub fn atoi(s: *const c_char) -> c_int;
pub fn sprintf(buf: *mut c_char, fmt: *const c_char, ...) -> c_int;
#[optional]
pub fn strlcpy(dst: *mut c_char, src: *const c_char, size: usize) -> usize;
}
}
}
fn main() -> dlsym::Result<()> {
#[cfg(unix)]
let lib = Library::this()?;
#[cfg(windows)]
let lib = unsafe { Library::open("msvcrt.dll") }?;
let libc = LibC::load(lib)?;
println!("labs(-42) = {}", libc.labs(-42));
unsafe {
println!("strlen(\"dlsym\") = {}", libc.strlen(c"dlsym".as_ptr()));
println!("atoi(\"123\") = {}", libc.atoi(c"123".as_ptr()));
}
let mut buf = [0 as c_char; 32];
unsafe {
libc.sprintf()
.with(|f| f(buf.as_mut_ptr(), c"%05.1f".as_ptr(), 2.5f64))
};
println!("sprintf = {:?}", unsafe { CStr::from_ptr(buf.as_ptr()) });
match unsafe { libc.strlcpy(buf.as_mut_ptr(), c"x".as_ptr(), buf.len()) } {
Some(n) => println!("strlcpy is available ({n})"),
None => println!("strlcpy is not available in this C library"),
}
Ok(())
}