{"id":30266734,"url":"https://github.com/xxshady/relib","last_synced_at":"2025-08-15T23:19:03.450Z","repository":{"id":267190920,"uuid":"900508292","full_name":"xxshady/relib","owner":"xxshady","description":"a framework for reloadable dynamic libraries (plugins) in Rust","archived":false,"fork":false,"pushed_at":"2025-07-09T12:33:08.000Z","size":274,"stargazers_count":28,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-13T04:44:20.570Z","etag":null,"topics":["dll","dynamic-library","hot-reload","live-reload","rust","rust-plugins"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xxshady.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-12-08T23:48:26.000Z","updated_at":"2025-07-09T12:33:11.000Z","dependencies_parsed_at":"2024-12-09T00:17:42.351Z","dependency_job_id":"a4ac00ae-663b-4dd6-822f-f1d542c0c4ff","html_url":"https://github.com/xxshady/relib","commit_stats":null,"previous_names":["xxshady/relib"],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/xxshady/relib","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xxshady%2Frelib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xxshady%2Frelib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xxshady%2Frelib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xxshady%2Frelib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xxshady","download_url":"https://codeload.github.com/xxshady/relib/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xxshady%2Frelib/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270482340,"owners_count":24591342,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-14T02:00:10.309Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dll","dynamic-library","hot-reload","live-reload","rust","rust-plugins"],"created_at":"2025-08-15T23:19:02.756Z","updated_at":"2025-08-15T23:19:03.432Z","avatar_url":"https://github.com/xxshady.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# relib\n\n`relib` is a framework for reloadable dynamic libraries written in Rust.\n\n[![demo](https://github.com/user-attachments/assets/44c87053-8aa1-462f-929f-2a355328387c)](https://github.com/user-attachments/assets/e2da4817-237a-4e90-9c5e-b6f24e4ad57c)\n\n## Platforms supported\n\nLinux and Windows are fully supported, macOS is not supported (not tested), see [support matrix](https://docs.rs/relib/latest/relib/docs/index.html#feature-support-matrix).\n\n## Overview\n\n`relib` tries to be a safe (as much as possible) runtime of native, almost normal Rust programs. Programs that can be safely unloaded (without memory leaks and crashes) without closing the whole OS process.\n\nSince it's not possible to make this completely safe: memory leaks, UB can still happen (for example, due to some unsafe call to C library), you should only use unloading for development (see [live reload](https://github.com/xxshady/relib/tree/main/examples/README.md#live-reload) example). `relib` can also be used without unloading, see [\"Usage without unloading\"](https://docs.rs/relib/latest/relib/docs/index.html#usage-without-unloading).\n\nSee [feature support matrix](https://docs.rs/relib/latest/relib/docs/index.html#feature-support-matrix) for what `relib` offers to improve unloading of dynamic libraries in Rust. And for what not, check out [caveats](#caveats).\n\n## Examples\n\nSee [examples](https://github.com/xxshady/relib/tree/main/examples/README.md).\n\n## Docs\n\nSee [`docs`](https://docs.rs/relib/latest/relib/docs/index.html) of `relib` crate.\n\n## Caveats\n\n### Imports/exports runtime validation\n\n*Currently*, `relib` doesn't check in runtime that function signatures (arguments, return types) specified in imports and exports traits (`main` and [`before_unload`](https://docs.rs/relib/latest/relib/docs/index.html#before_unload) as well) are exactly the same for host and module.\n\n### ABI stability\n\n\u003e [Why would I want a stable ABI? And what even is an ABI?](https://docs.rs/stabby/latest/stabby/#why-would-i-want-a-stable-abi-and-what-even-is-an-abi)\n\nTo ensure at least something about ABI `relib` **checks and requires that host and module are compiled with the same rustc and `relib` version**.\n\nFor ABI stable types, you can use abi_stable or stabby crate for it, see `abi_stable` usage [example](https://github.com/xxshady/relib/tree/main/examples/README.md#usage-with-abi_stable-crate).\n\n### File descriptors and network sockets\n\n*Currently*, `relib` knows nothing about file descriptors or network sockets (unlike [background threads](https://docs.rs/relib/latest/relib/docs/index.html#background-threads-check)) so, for example, if your program stores them in static items and does not properly close them they will leak after unloading.\n\n**note:** relib provides [`before_unload`](https://docs.rs/relib/latest/relib/docs/index.html#before_unload) callback API when you need to cleanup something manually (similar to Rust Drop).\n\n### Dead locks\n\nIf your program (module) deadlocks unloading won't work and you will have to kill the whole process.\n\n### Moving non-`Copy` types between host and module\n\n#### Return values\n\nNon-`Copy` types (for example, a heap allocated string) are always implicitly cloned (and must implement `Clone` trait) on host-module boundary when returned from an export or import. Since host and module can use different global [allocators](https://doc.rust-lang.org/stable/std/alloc/index.html) and [`dealloc`](https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html#tymethod.dealloc) expects a pointer allocated exactly via this global allocator.\n\nFor example:\n```rust\n// a type that is common for host and module\n#[repr(C)]\n#[derive(Debug)]\nstruct MemoryChunk {\n  ptr: *const u8,\n  len: usize,\n}\n\n// allocates new chunk of memory using global allocator (will be called in generated bindings)\nimpl Clone for MemoryChunk { ... }\n\n// deallocates it (will be called in generated bindings)\nimpl Drop for MemoryChunk { ... }\n\n// host:\nimpl Imports for ModuleImportsImpl {\n  fn example() -\u003e MemoryChunk {\n    MemoryChunk { ... }\n  }\n}\n\n// module:\n// returned value will be implicitly cloned by using Clone trait\nlet chunk: MemoryChunk = unsafe { gen_imports::example() }; // gen_imports is defined by relib_interface::include_imports!()\n```\n\n##### Some notes\n\n- Reference-counting pointers don't allocate new memory when cloned, but reuse old one, so they **must not be** moved through module-host boundary (Rc or Arc in std, but keep in mind that these std types don't have [stable ABI](#abi-stability)).\n\n- It's still possible to use raw pointers to avoid cloning if you're sure of what you're doing.\n\n#### Parameters\n\nParameters are limited to `Copy` types, moving non-`Copy` types is not possible.\n\nFor example:\n```rust\n// a type that is common for host and module\n#[repr(C)]\n#[derive(Debug)]\nstruct MemoryChunk {\n  ptr: *const u8,\n  len: usize,\n}\n\n// allocates new chunk of memory using global allocator\nimpl Clone for MemoryChunk { ... }\n\n// deallocates it\nimpl Drop for MemoryChunk { ... }\n\n// host:\nimpl Imports for ModuleImportsImpl {\n  fn example(chunk: \u0026MemoryChunk) {\n    // if owned value is needed just call .to_owned() explicitly:\n    let chunk = chunk.to_owned();\n  }\n}\n\n// module:\nlet chunk = MemoryChunk { ... };\nunsafe { gen_imports::example(\u0026chunk) }; // gen_imports is defined by relib_interface::include_imports!()\n```\n\n##### Why parameters are limited to `Copy` types?\n\nBecause when you can you should pass values by reference to avoid cost of the cloning allocations.\n\nIt is the same reason as with return values: host and module can use different global [allocators](https://doc.rust-lang.org/stable/std/alloc/index.html) and [`dealloc`](https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html#tymethod.dealloc) expects a pointer allocated exactly via this global allocator. So if moving non-`Copy` types would be possible `relib` would still clone parameters implicitly.\n\n### Lifetime elision in imports and exports\n\nDue to the code generation this code may not compile: (`RStr` is FFI-safe equivalent of `\u0026str` from [abi_stable](https://docs.rs/abi_stable/latest/abi_stable/std_types/struct.RStr.html))\n\n```rust\n// shared:\npub trait Exports {\n  fn ret_ref(str: RStr) -\u003e RStr;\n}\n\n// module:\nimpl Exports for ModuleExportsImpl {\n  fn ret_ref(str: RStr) -\u003e RStr {\n    str.slice(..) // equal to str[..]\n  }\n}\n```\n\nWill result in:\n```txt\nerror[E0621]: explicit lifetime required in the type of `str`\n   --\u003e .../generated_module_exports.rs:234:9\n```\n\nIn order to fix it you need add explicit lifetime to trait\n\n```rust\npub trait Exports {\n  fn ret_ref\u003c'a\u003e(str: RStr\u003c'a\u003e) -\u003e RStr\u003c'a\u003e;\n}\n```\n\n### Lifetime bounds in imports and exports\n\nIt's not possible specify lifetime bounds for imports and exports as it's too complex to implement (there is no `for\u003c'a, 'b: 'a\u003e fn(...)` syntax).\n\nExample: (`RStr` is FFI-safe equivalent of `\u0026str` from [abi_stable](https://docs.rs/abi_stable/latest/abi_stable/std_types/struct.RStr.html))\n\n```rust\npub trait Exports {\n  fn returns_b\u003c'a, 'b: 'a\u003e(a: RStr\u003c'a\u003e, b: RStr\u003c'b\u003e) -\u003e RStr\u003c'a\u003e {\n    b\n  }\n}\n```\n\n### Each module has its own standard library\n\nEach compiled module (.dll or .so) uses its own copy of standard library. Because of this, for example, [`std::thread::current().id()`](https://doc.rust-lang.org/stable/std/thread/fn.current.html) called in a module may return different id compared to the host, since each module has it's own thread id counter (in this particular case you can use [thread_id](https://docs.rs/thread-id) instead to get thread identifiers from operating system).\n\n## Why dynamic libraries when we already have WASM?\n\nIf you can you should use WebAssembly since it's much more memory-safe approach. But what if WASM is not enough for you for some of these reasons: (some of which may be resolved in the future)\n\n- you need to communicate with C++ or C\n- you want to use all features of Rust (for example, multi threading, panics, backtraces may not be supported really well in WASM ecosystem)\n- you've already written something in normal Rust and don't want to rewrite it to work in WASM\n- you don't need sandboxing/isolation\n- performance\n- bugs in WASM runtimes\n\n## Resources that helped me create this tool\n\nAwesome fasterthanlime's article ❤️ \u003chttps://fasterthanli.me/articles/so-you-want-to-live-reload-rust\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxxshady%2Frelib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxxshady%2Frelib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxxshady%2Frelib/lists"}