#![cfg(windows)] #![allow(non_snake_case)] use minidl::*; use std::fmt::{self, Debug, Formatter}; use std::io::Result; use std::os::raw::*; #[allow(dead_code)] struct Example { OutputDebugStringA: unsafe extern "system" fn (_: *const c_char), Invalid_Optional: Option, Invalid_Required: unsafe extern "system" fn (_: *const c_char), } impl Example { pub fn new() -> Result { Self::from(Library::load("kernel32.dll")?) } pub fn from(lib: Library) -> Result { unsafe{Ok(Self{ OutputDebugStringA: lib.sym("OutputDebugStringA\0")?, Invalid_Optional: lib.sym_opt("Invalid_Optional\0"), Invalid_Required: lib.sym("Invalid_Required\0")?, })} } } impl Debug for Example { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { write!(fmt, "Example {{ ... }}") } } #[test] fn bad_load() { let e = Library::load("does_not_exist_invalid.dll").expect_err("Invalid DLL should've failed to load"); let e = format!("{}", e); assert!(e.contains("does_not_exist_invalid"), "{}", e); } #[test] fn bad_sym() { let e = Example::new().expect_err("Example should've failed to load Invalid_Required"); let e = format!("{}", e); assert!(!e.contains("Invalid_Optional"), "{}", e); assert!( e.contains("Invalid_Required"), "{}", e); } #[test] fn ok_sym() { unsafe { let OutputDebugStringA : unsafe extern "system" fn (_: *const c_char) = Library::load("kernel32.dll").unwrap() .sym("OutputDebugStringA\0").unwrap(); OutputDebugStringA(b"Hello, world!\0".as_ptr() as _); } }