What's causing this failure to load the first procedure requested from a DLL?

I'm loading function pointers from a DLL at runtime. However, the first function pointer to be loaded is always None. It's not because the function does not exist - if I swap the order, it is still always the first function that is None.

I'm using Windows GetProcAddress:

type XInputGetStateFn = unsafe extern "system" fn(user_index: DWORD, state: *mut XINPUT_STATE) -> DWORD;
type XInputSetStateFn = unsafe extern "system" fn(user_index: DWORD, vibration: *mut XINPUT_VIBRATION) -> DWORD;

static mut X_INPUT_GET_STATE: XInputGetStateFn = x_input_get_state_stub;
static mut X_INPUT_SET_STATE: XInputSetStateFn = x_input_set_state_stub;

fn load_x_input() {
    if let Some(x_input_library) = load_library(&"xinput1_4.dll".into()) {
        if let Some(get_state) = get_proc_address(x_input_library, "XInputGetState") {
            unsafe { X_INPUT_GET_STATE = get_state };
        }

        if let Some(set_state) = get_proc_address(x_input_library, "XInputSetState") {
            unsafe { X_INPUT_SET_STATE = set_state };
        }
    }
}

pub fn get_proc_address<T>(module: ModuleHandle, name: &str) -> Option<T> {
    let ptr = unsafe { GetProcAddress(module.0, name.as_ptr()) };

    if ptr.is_null() {
        None
    } else {
        unsafe { Some(std::mem::transmute_copy(&ptr)) }
    }
}

I wondered if the slowness was due to being a debug build and various checks being performed (probably when loading the library DLL?), but the problem occurs even in a release build. I've not experienced this problem with the equivalent code in C/C++.

What's causing this and how can it be prevented from happening?

You most likely need to pass a null-terminated string to GetProcAddress. Easiest way to do this is using CString (or if you always work with fixed strings like in your code above manually appending the zero-byte would work too)

Thanks @jer . What's funny is that I do exactly that when creating my wide strings - but the proc name is indeed a null-terminated const CHAR not a WCHAR and I completely missed that!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.