-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This was a little tricky to get working: - Add a few extra dependencies to the dev-dependencies which are required by the two libraries. - The plugin library itself will not be automatically compiled with the binary that loads it, but there's no way in Cargo to fix that without making them direct dependencies (which we explicitly don't want) - For both binaries (executable and library) to use the same bevy library instance, it needs to be dynamically linked. The only real way (while keeping both as "example" binaries) to do this is to include the dynamic library version of bevy as a dev dependency, thereby making tests and example use the dynamically-linked bevy.
- Loading branch information
1 parent
1fe7a72
commit af6f9ee
Showing
3 changed files
with
77 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
//! A dynamic library that contains a dynamically loaded plugin. See the `load_dynamic_plugin` on how to load such a plugin. | ||
use bevy::prelude::*; | ||
|
||
/// Derive DynamicPlugin on one main plugin, which will then be loaded by [`bevy_dynamic_plugin::load_dynamic_plugin`]. | ||
#[derive(DynamicPlugin)] | ||
struct MyDynamicPlugin; | ||
|
||
impl Plugin for MyDynamicPlugin { | ||
fn build(&self, app: &mut App) { | ||
info!("Plugin is being loaded..."); | ||
app.add_systems(Update, say_hello); | ||
} | ||
} | ||
|
||
fn say_hello() { | ||
info!("Hello from the dynamic plugin!"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
//! Loads a dynamic plugin from the shared library `dynamic_plugin` | ||
use std::path::PathBuf; | ||
|
||
use bevy::prelude::*; | ||
use bevy_dynamic_plugin::dynamically_load_plugin; | ||
use libloading::Library; | ||
use parking_lot::Mutex; | ||
|
||
/// If the library wasn't stored here, libloading would unload it as soon as we were done with it below. | ||
/// This would cause the program to crash/segfault later when bevy tries to invoke the plugin's systems. | ||
/// Therefore, libraries should be stored such that they outlive the [`App`]. | ||
/// A simple method is to use a global mutex. | ||
static LIBRARY: Mutex<Option<Library>> = Mutex::new(None); | ||
|
||
fn main() { | ||
let mut app = App::new(); | ||
app.add_plugins(DefaultPlugins); | ||
|
||
#[cfg(any(target_family = "windows", target_family = "unix"))] | ||
{ | ||
// The ending can be the default library ending of the operating system (e.g. .dll, .so). | ||
let plugin_name = PathBuf::from("dynamic_plugin"); | ||
|
||
let (library, plugin) = unsafe { dynamically_load_plugin(plugin_name) }.unwrap(); | ||
app.add_plugins(plugin); | ||
info!("Loaded plugin!"); | ||
// Make sure the plugin stays alive by storing it in a global variable: | ||
*LIBRARY.lock() = Some(library); | ||
} | ||
|
||
app.run(); | ||
} |