• Stars
    star
    351
  • Rank 116,786 (Top 3 %)
  • Language
    Rust
  • License
    Apache License 2.0
  • Created over 8 years ago
  • Updated 9 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Dynamic reloading of shared libraries

Build Status Coverage Status Crates.io Documentation

dynamic_reload is a cross platform library written in Rust that makes it easier to do reloading of shared libraries (dll:s on windows, .so on *nix, .dylib on Mac, etc). The intended use is to allow applications to reload code on the fly without closing down the application when some code changes. This can be seen as a lite version of "live" coding for Rust. It's worth to mention here that reloading of shared libraries isn't limited to libraries written in Rust but can be done in any language that can target shared libraries. A typical scenario can look like this:

1. Application Foo starts.
2. Foo loads the shared library Bar.
3. The programmer needs to make some code changes to Bar.
   Instead of closing down Foo the programmer does the change, recompiles the code.
4. Foo will detect that Bar has been changed on the disk,
   will unload the old version and load the new one.

dynamic_reload library will not try to solve any stale data hanging around in Foo from Bar. It is up to Foo to make sure all data has been cleaned up before Foo is reloaded. Foo will be getting a callback from dynamic_reload before Bar is reloaded and that allows Foo to take needed action. Then another call will be made after Bar has been reloaded to allow Foo to restore state for Bar if needed.

Usage

# Cargo.toml
[dependencies]
dynamic_reload = "0.10.0"

Example

To actually test reloading of this example do the following

1, cargo run --example example
2. In another shell change src/test_shared.rs to return another value
3. Run cargo build
4. Notice that the value return in 1. is now changed
use dynamic_reload::{DynamicReload, Lib, Symbol, Search, PlatformName, UpdateState};
use std::{sync::Arc, time::Duration, thread};

struct Plugins {
    plugins: Vec<Arc<Lib>>,
}

impl Plugins {
    fn add_plugin(&mut self, plugin: &Arc<Lib>) {
        self.plugins.push(plugin.clone());
    }

    fn unload_plugins(&mut self, lib: &Arc<Lib>) {
        for i in (0..self.plugins.len()).rev() {
            if &self.plugins[i] == lib {
                self.plugins.swap_remove(i);
            }
        }
    }

    fn reload_plugin(&mut self, lib: &Arc<Lib>) {
        Self::add_plugin(self, lib);
    }

    // called when a lib needs to be reloaded.
    fn reload_callback(&mut self, state: UpdateState, lib: Option<&Arc<Lib>>) {
        match state {
            UpdateState::Before => Self::unload_plugins(self, lib.unwrap()),
            UpdateState::After => Self::reload_plugin(self, lib.unwrap()),
            UpdateState::ReloadFailed(_) => println!("Failed to reload"),
        }
    }
}

fn main() {
    let mut plugs = Plugins { plugins: Vec::new() };

    // Setup the reload handler. A temporary directory will be created inside the target/debug
    // where plugins will be loaded from. That is because on some OS:es loading a shared lib
    // will lock the file so we can't overwrite it so this works around that issue.
    let mut reload_handler = DynamicReload::new(Some(vec!["target/debug"]),
                                                Some("target/debug"),
                                                Search::Default,
                                                Duration::from_sec(2));

    // test_shared is generated in build.rs
    match reload_handler.add_library("test_shared", PlatformName::Yes) {
        Ok(lib) => plugs.add_plugin(&lib),
        Err(e) => {
            println!("Unable to load dynamic lib, err {:?}", e);
            return;
        }
    }

    //
    // While this is running (printing a number) change return value in file src/test_shared.rs
    // build the project with cargo build and notice that this code will now return the new value
    //
    loop {
        reload_handler.update(Plugins::reload_callback, &mut plugs);

        if plugs.plugins.len() > 0 {
            // In a real program you want to cache the symbol and not do it every time if your
            // application is performance critical
            let fun: Symbol<extern "C" fn() -> i32> = unsafe {
                plugs.plugins[0].lib.get(b"shared_fun\0").unwrap()
            };

            println!("Value {}", fun());
        }

        // Wait for 0.5 sec
        thread::sleep(Duration::from_millis(500));
    }
}

Acknowledgment

dynamic_reload uses these two crates for most of the heavy lifting. Thanks!

Notify: https://github.com/passcod/rsnotify

libloading: https://github.com/nagisa/rust_libloading/

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

More Repositories

1

minifb

MiniFB is a small cross platform library to create a frame buffer that you can draw pixels in
C
924
star
2

rust_minifb

Cross platfrom window and framebuffer crate for Rust
Rust
887
star
3

ProDBG

Debugging the way it's meant to be done
C++
513
star
4

rocket

GNU Rocket Git mirror
Lua
107
star
5

bgfx-rs

Rust wrapper for BGFX
Rust
84
star
6

Score

Score! is a new programming language based on the ideas from GOAL
Common Lisp
46
star
7

Rute

Rute is a UI library implemented on top of Qt
Rust
39
star
8

evfs

Virtual File System written in Rust
Rust
37
star
9

remotery-rs

Realtime CPU Profiler with web browser viewer
Rust
31
star
10

AmigaHunkParser

Parser written in C for Amiga Hunk (executable) files
C
13
star
11

cfixed-string

Pass Rust strings to C with potentially not needing heap allocation
Rust
13
star
12

ps2dev_tools

Binaries of the ps2dev toolchain (for win32 and osx)
C
12
star
13

remotelink

Remote running executables on a Linux style system
Rust
9
star
14

wrui

C wrapper for UI libraries (like Qt, wxWidgets, dear imgui) with a common C API
Lua
8
star
15

sico

SICO - SImple COmpute
Lua
8
star
16

Arika

Arika is a cross-platform UI library written in C and Lua
C
7
star
17

usb2snes

Rust crate for talking with SD2SNES over USB
Rust
6
star
18

csimd

Cross platform SIMD intrinsics in C
5
star
19

bgfx-sys

Rust FFI bindings for bgfx
C
5
star
20

m68k_cpu_tester_api

Uses data from the (Win)UAE cpu test generator
C
4
star
21

flowi

Flowi is a research UI aimed at speed, good looks and ease of use
C
4
star
22

amiga_hunk_parser

Parses Amiga exceutable (hunk files) in Rust
Rust
4
star
23

text_render

Fiddling around with Text Rendering to make something that looks less crap
Rust
4
star
24

modland_hash

Rust
3
star
25

68k_disassemble_gen

68k disassembler for C made in Rust
Rust
3
star
26

dotvim

vimconfig files and plugins
Vim Script
2
star
27

prodbg_addons

Addons/Plugins to ProDBG
C++
2
star
28

ssagen

Playing around with SSA form
C
2
star
29

wrui_rust

Rust wrapper for WRUI
Rust
2
star
30

prodbg-web

Webpages for ProDBG
JavaScript
2
star
31

68k_documentation_gen

Generate documentation including cycle tables for Motorola 680x0
C
2
star
32

docking_system

Docking system based on the i3wm code
Lua
1
star
33

apigen

Basic API/data description lang + parser that can be used for generating API/data interfaces, etc
Rust
1
star
34

extract-opencl-docs-dash

Script that is used for generating OpenCL docs for Dash
Python
1
star
35

dms-rs

DMS (Amiga Disk Masher System) unpacker written in Rust
Rust
1
star
36

bgfx-rs-bindgen

Rust binding generator for bgfx
Rust
1
star
37

IMCocoa

Experimental project to try to do Immediate mode GUI in Cocoa (Mac OS X)
Objective-C
1
star
38

flowi_rust

Lets do Flowi in Rust instead
1
star
39

prodbg-third-party

Third Party libs used by ProDBG
C++
1
star
40

scintilla

Scintilla is a free source code editing component.
C++
1
star
41

anidb-rs

Rust crate that makes using the AniDB API easier
Rust
1
star
42

fx68x_verilator

verilator testing of fx68k
C++
1
star