Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The "Dynamic Loading & Plugins" chapter example code causes a segfault on Windows #78

Open
zrneely opened this issue Mar 15, 2019 · 1 comment

Comments

@zrneely
Copy link

zrneely commented Mar 15, 2019

The chapter gives this example of loading a plugin:

pub unsafe fn load_plugin<P: AsRef<OsStr>>(&mut self, filename: P) -> Result<()> {
    type PluginCreate = unsafe fn() -> *mut Plugin;

    let lib = Library::new(filename.as_ref()).chain_err(|| "Unable to load the plugin")?;

    // We need to keep the library around otherwise our plugin's vtable will
    // point to garbage. We do this little dance to make sure the library
    // doesn't end up getting moved.
    self.loaded_libraries.push(lib);

    let lib = self.loaded_libraries.last().unwrap();

    let constructor: Symbol<PluginCreate> = lib.get(b"_plugin_create")
        .chain_err(|| "The `_plugin_create` symbol wasn't found.")?;
    let boxed_raw = constructor();

    let plugin = Box::from_raw(boxed_raw);
    debug!("Loaded plugin: {}", plugin.name());
    plugin.on_plugin_load();
    self.plugins.push(plugin);


    Ok(())
}

However (in my testing, which has only been on Windows 10), this code crashes unless I change the type alias to:

type PluginCreate = unsafe extern "C" fn() -> *mut Plugin;

With the addition of extern "C", everything appears to work correctly.

@Michael-F-Bryan
Copy link
Owner

Thanks for pointing that out @zrneely. I had a look at The Reference and it sounds like extern defaults to stdcall or win64 on Windows machines and the C ABI (cdecl) everywhere else. I wrote this guide on a Linux machine, so I'm guessing that's why it was never a problem for me.

Would you be able to make a PR fixing the code, and (if you feel it's worth it) maybe add a paragraph explaining the situation (i.e. defaults for extern and what happens when you use the wrong calling convention) so others can learn from it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants