minidl 0.1.6

Extremely lean cross platform library for loading symbols
Documentation
#![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<unsafe extern "system" fn (_: *const c_char)>,
    Invalid_Required:   unsafe extern "system" fn (_: *const c_char),
}

impl Example {
    pub fn new() -> Result<Self> {
        Self::from(Library::load("kernel32.dll")?)
    }

    pub fn from(lib: Library) -> Result<Self> {
        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 _);
    }
}