### Example: Obtain Address Information Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/raw/common.rs.html Demonstrates how to open a library, get a symbol's pointer, and then use AddressInfoObtainer to retrieve details about that pointer, printing the library path and symbol information. ```rust use dlopen2::raw::{Library, AddressInfoObtainer}; fn main() { let lib = Library::open("libyourlib.so").unwrap(); let ptr: * const i32 = unsafe{ lib.symbol("symbolname") }.unwrap(); // now we can obtain information about the symbol - library, base address etc. let aio = AddressInfoObtainer::new(); let addr_info = unsafe { aio.obtain(ptr as * const ()) }.unwrap(); println!("Library path: {}", &addr_info.dll_path); println!("Library base address: {:?}", addr_info.dll_base_addr); if let Some(os) = addr_info.overlapping_symbol{ println!("Overlapping symbol name: {}", &os.name); println!("Overlapping symbol address: {:?}", os.addr); } } ``` -------------------------------- ### Example Usage of Container with WrapperApi Source: https://docs.rs/dlopen2/0.8.2/dlopen2/wrapper/struct.Container.html Demonstrates how to load a dynamic library and use its functions and variables through a generated wrapper. Ensure the `wrapper` feature is enabled. The `Example` struct defines the interface to the dynamic library's symbols. ```rust use dlopen2::wrapper::{Container, WrapperApi}; use std::os::raw::{c_char}; use std::ffi::CStr; #[derive(WrapperApi)] struct Example<'a> { do_something: extern "C" fn(), add_one: unsafe extern "C" fn (arg: i32) -> i32, global_count: &'a mut u32, c_string: * const c_char } //wrapper for c_string won't be generated, implement it here impl<'a> Example<'a> { pub fn c_string(&self) -> &CStr { unsafe {CStr::from_ptr(self.c_string)} } } fn main () { let mut container: Container = unsafe { Container::load("libexample.dylib")}.unwrap(); container.do_something(); let _result = unsafe { container.add_one(5) }; *container.global_count_mut() += 1; println!("C string: {}", container.c_string().to_str().unwrap()) } ``` -------------------------------- ### Quick Example of dlopen2 Usage Source: https://docs.rs/dlopen2/0.8.2/dlopen2/index.html Demonstrates how to load a dynamic library and access its functions and fields using the high-level API. Requires the library 'libexample.so' to be available. ```rust use dlopen2::wrapper::{Container, WrapperApi}; #[derive(WrapperApi)] struct Api<'a> { example_rust_fun: fn(arg: i32) -> u32, example_c_fun: unsafe extern "C" fn(), example_reference: &'a mut i32, // A function or field may not always exist in the library. example_c_fun_option: Option, example_reference_option: Option<&'a mut i32>, } fn main() { let mut cont: Container = unsafe { Container::load("libexample.so") }.expect("Could not open library or load symbols"); cont.example_rust_fun(5); unsafe { cont.example_c_fun() }; *cont.example_reference_mut() = 5; // Optional functions return Some(result) if the function is present or None if absent. unsafe { cont.example_c_fun_option() }; // Optional fields are Some(value) if present and None if absent. if let Some(example_reference) = cont.example_reference_option() { *example_reference = 5; } } ``` -------------------------------- ### Implement WrapperMultiApi with Derive Source: https://docs.rs/dlopen2/0.8.2/dlopen2/wrapper/trait.WrapperMultiApi.html Example showing how to define multiple sub-APIs and combine them into a single multi-wrapper structure using the derive macro. ```rust use dlopen2::wrapper::{Container, WrapperApi, WrapperMultiApi}; //Define 3 APIs: #[derive(WrapperApi)] struct Obligatory{ some_fun: unsafe extern "C" fn() } #[derive(WrapperApi)] struct Optional1<'a>{ static_val: &'a i32 } #[derive(WrapperApi)] struct Optional2{ another_fun: unsafe extern "C" fn() } //Now define a multi wrapper that wraps sub APIs into one bigger API. //This example assumes that the first API is obligatory and the other two are optional. #[derive(WrapperMultiApi)] struct Api<'a>{ pub obligatory: Obligatory, pub optional1: Option>, pub optional2: Option } fn main(){ let mut container: Container = unsafe { Container::load("libexample.so") }.expect("Could not open library or load symbols"); //use obligatory API: unsafe{container.obligatory.some_fun()}; //use first optional API: if let Some(ref opt) = container.optional1{ let _val = *opt.static_val(); } //use second optional API: if let Some(ref opt) = container.optional2{ unsafe {opt.another_fun()}; } } ``` -------------------------------- ### Get Raw OS Handle Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/raw/common.rs.html Returns the raw operating system handle for the opened library. This should only be used if absolutely necessary. ```rust pub unsafe fn into_raw(&self) -> Handle { self.handle } ``` -------------------------------- ### Implement SymBorApi with derive macro Source: https://docs.rs/dlopen2/0.8.2/dlopen2/symbor/trait.SymBorApi.html Example showing how to define a structure with symbols and load them from a library. Requires the symbor feature. ```rust use dlopen2::symbor::{Library, Symbol, SymBorApi, PtrOrNull, RefMut, PtrOrNullMut}; use std::os::raw::{c_double, c_char}; #[derive(SymBorApi)] struct Example<'a> { pub simple_fun: Symbol<'a, unsafe extern "C" fn()>, pub complex_fun: Symbol<'a, unsafe extern "C" fn(c_double)->c_double>, pub optional_fun: Option>, pub nullable_ptr: PtrOrNullMut<'a, c_char>, pub mut_ref_i32: Symbol<'a, &'a mut i32>, #[dlopen2_name="mut_ref_i32"] pub the_same_mut_ref_i32: RefMut<'a, i32>, pub not_nullable_ptr: Symbol<'a, * mut c_double> } fn main(){ let lib = Library::open("example.dll").expect("Could not open library"); let mut api = unsafe{Example::load(&lib)}.expect("Could not load symbols"); unsafe{(api.simple_fun)()}; let _ = unsafe{(api.complex_fun)(1.0)}; match api.optional_fun { Some(fun) => unsafe {fun()}, None => println!("Optional function could not be loaded"), }; if api.nullable_ptr.is_null(){ println!("Library has a null symbol"); } //while Symbol is good for everything, RefMut requires one less dereference to use **api.mut_ref_i32 =34; *api.the_same_mut_ref_i32 =35; unsafe{**api.not_nullable_ptr = 55.0}; unsafe{**api.nullable_ptr = 0}; } ``` -------------------------------- ### Example Usage of OptionalContainer Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/wrapper/optional.rs.html Demonstrates how to load a library with both obligatory and optional APIs, access the obligatory API directly, and conditionally access the optional API. ```rust use dlopen2::wrapper::{OptionalContainer, WrapperApi}; #[derive(WrapperApi)] struct Obligatory<'a> { do_something: extern "C" fn(), global_count: &'a mut u32, } #[derive(WrapperApi)] struct Optional{ add_one: unsafe extern "C" fn (arg: i32) -> i32, c_string: * const u8 } fn main () { let mut container: OptionalContainer = unsafe { OptionalContainer::load("libexample.dylib") }.unwrap(); container.do_something(); *container.global_count_mut() += 1; match container.optional(){ &Some(ref opt) => { let _result = unsafe { opt.add_one(5) }; println!("First byte of C string is {}", unsafe{*opt.c_string}); }, &None => println!("The optional API was not loaded!") } } ``` -------------------------------- ### Load library and access symbols using Container Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/symbor/container.rs.html Demonstrates loading a dynamic library and accessing its symbols through a Container. This example requires the "libexample.so" library to be available and accessible. ```rust fn main(){ let cont: Container = unsafe{Container::load("libexample.so")} .expect("Could not load library or symbols"); println!("fun(4)={}", unsafe{(cont.fun)(4)}); println!("glob_i32={}", *cont.glob_i32); println!("The pointer is null={}", cont.maybe_c_str.is_null()); } ``` -------------------------------- ### Example Usage of dlopen2 Library Source: https://docs.rs/dlopen2/0.8.2/dlopen2/symbor/struct.Library.html Demonstrates opening a dynamic library, obtaining a function symbol, calling it, accessing a mutable global variable, and checking a null pointer. Ensure the 'symbor' feature is enabled. ```rust use dlopen2::symbor::Library; fn main(){ let mut lib = Library::open("libexample.dylib").unwrap(); let fun = unsafe{lib.symbol::( "function")}.unwrap(); unsafe{fun()}; let glob_val: &mut u32 = unsafe{lib.reference_mut("glob_val")}.unwrap(); *glob_val = 42; let ptr_or_null = unsafe{lib.ptr_or_null::<()>( "void_ptr")}.unwrap(); println!("Pointer is null: {}", ptr_or_null.is_null()); } ``` -------------------------------- ### Load Library with Optional Container Source: https://docs.rs/dlopen2/0.8.2/dlopen2/wrapper/struct.OptionalContainer.html Load a dynamic library using OptionalContainer, specifying both obligatory and optional API types. This example demonstrates loading 'libexample.dylib'. ```rust fn main () { let mut container: OptionalContainer = unsafe { OptionalContainer::load("libexample.dylib") }.unwrap(); container.do_something(); *container.global_count_mut() += 1; match container.optional(){ &Some(ref opt) => { let _result = unsafe { opt.add_one(5) }; println!("First byte of C string is {}", unsafe{*opt.c_string}); }, &None => println!("The optional API was not loaded!") } } ``` -------------------------------- ### Define and Use a Dynamic Library API with Container Source: https://docs.rs/dlopen2/0.8.2/dlopen2/symbor/struct.Container.html This example demonstrates how to define a struct that implements `SymBorApi` to represent symbols from a dynamic library. It then shows how to load the library using `Container::load` and access its functions and variables. ```rust use dlopen2::symbor::{Library, Symbol, Ref, PtrOrNull, SymBorApi, Container}; #[derive(SymBorApi)] struct ExampleApi<'a> { pub fun: Symbol<'a, unsafe extern "C" fn(i32) -> i32>, pub glob_i32: Ref<'a, i32>, pub maybe_c_str: PtrOrNull<'a, u8>, } fn main(){ let cont: Container = unsafe{Container::load("libexample.so")} .expect("Could not load library or symbols"); println!("fun(4)={}", unsafe{(cont.fun)(4)}); println!("glob_i32={}", *cont.glob_i32); println!("The pointer is null={}", cont.maybe_c_str.is_null()); } ``` -------------------------------- ### Get Raw OS Handle of Library Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/symbor/library.rs.html Returns the raw OS handle for the opened library. This is `HMODULE` on Windows and `*mut c_void` on Unix systems. Use only when absolutely necessary. ```rust pub unsafe fn into_raw(&self) -> raw::Handle { unsafe { self.lib.into_raw() } } ``` -------------------------------- ### Get Raw OS Handle of the Library Source: https://docs.rs/dlopen2/0.8.2/dlopen2/symbor/struct.Container.html The `into_raw` method returns the raw operating system handle for the opened dynamic library. This handle is of type `HMODULE` on Windows and `*mut c_void` on Unix systems. It should only be used when absolutely necessary. ```rust pub unsafe fn into_raw(&self) -> Handle ``` -------------------------------- ### Get raw OS handle from Container Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/symbor/container.rs.html Returns the raw operating system handle for the opened library. This method is unsafe and should only be used when absolutely necessary, as direct manipulation of the handle can lead to instability. ```rust pub unsafe fn into_raw(&self) -> raw::Handle { unsafe { self.lib.into_raw() } } ``` -------------------------------- ### Open Library and Get Symbol Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/raw/common.rs.html Opens a dynamic library and retrieves a symbol by name. Handles potential errors, including null symbols, by returning an Option or panicking. ```rust let lib = Library::open("libyourlib.so").unwrap(); let ptr_or_null: * const i32 = match unsafe{ lib.symbol("symbolname") } { Ok(val) => val, Err(err) => match err { Error::NullSymbol => null(), _ => panic!("Could not obtain the symbol") } }; //do something with the symbol ``` -------------------------------- ### Load and Use Dynamic Library Symbols Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/lib.rs.html Load a dynamic library using `Container::load` and access its symbols through the defined API structure. This example demonstrates calling a Rust function, an unsafe C function, modifying a mutable reference, and handling optional symbols. ```rust fn main() { let mut cont: Container = unsafe { Container::load("libexample.so") }.expect("Could not open library or load symbols"); cont.example_rust_fun(5); unsafe { cont.example_c_fun() }; *cont.example_reference_mut() = 5; // Optional functions return Some(result) if the function is present or None if absent. unsafe { cont.example_c_fun_option() }; // Optional fields are Some(value) if present and None if absent. if let Some(example_reference) = cont.example_reference_option() { *example_reference = 5; } } ``` -------------------------------- ### Define API for Container with dlopen2 Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/symbor/container.rs.html Defines a struct that implements SymBorApi for use with Container. This example shows how to declare symbols like functions, references, and nullable pointers. ```rust use dlopen2::symbor::{Library, Symbol, Ref, PtrOrNull, SymBorApi, Container}; #[derive(SymBorApi)] struct ExampleApi<'a> { pub fun: Symbol<'a, unsafe extern "C" fn(i32) -> i32>, pub glob_i32: Ref<'a, i32>, pub maybe_c_str: PtrOrNull<'a, u8>, } ``` -------------------------------- ### Generate Platform-Specific File Name Source: https://docs.rs/dlopen2/0.8.2/dlopen2/utils/fn.platform_file_name.html Use this function to create a library file name that is appropriate for the current operating system. For example, it adds the correct prefix and suffix for shared libraries. ```rust pub fn platform_file_name(core_name: S) -> OsString where S: AsRef, ``` -------------------------------- ### Define API Structure for Dynamic Library Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/lib.rs.html Define a struct that represents the API of the dynamic library. Use the `WrapperApi` derive macro to automatically generate wrapper functions for library symbols. This example shows how to define functions, unsafe extern C functions, and mutable references, including optional ones. ```rust use dlopen2::wrapper::{Container, WrapperApi}; #[derive(WrapperApi)] struct Api<'a> { example_rust_fun: fn(arg: i32) -> u32, example_c_fun: unsafe extern "C" fn(), example_reference: &'a mut i32, // A function or field may not always exist in the library. example_c_fun_option: Option, example_reference_option: Option<&'a mut i32>, } ``` -------------------------------- ### Obtain Symbol Information from Dynamic Library Source: https://docs.rs/dlopen2/0.8.2/dlopen2/raw/struct.AddressInfoObtainer.html Use AddressInfoObtainer to get details about a symbol loaded from a dynamic library. Requires opening the library and obtaining a symbol pointer first. ```rust use dlopen2::raw::{Library, AddressInfoObtainer}; fn main() { let lib = Library::open("libyourlib.so").unwrap(); let ptr: * const i32 = unsafe{ lib.symbol("symbolname") }.unwrap(); // now we can obtain information about the symbol - library, base address etc. let aio = AddressInfoObtainer::new(); let addr_info = unsafe { aio.obtain(ptr as * const ()) }.unwrap(); println!("Library path: {}", &addr_info.dll_path); println!("Library base address: {:?}", addr_info.dll_base_addr); if let Some(os) = addr_info.overlapping_symbol{ println!("Overlapping symbol name: {}", &os.name); println!("Overlapping symbol address: {:?}", os.addr); } } ``` -------------------------------- ### Mistake Example: Dangling Symbol in dlopen2 Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/symbor/mod.rs.html This example illustrates a potential mistake where a safe wrapper around a symbol is dereferenced, leading to a dangling symbol after the library is closed. The `raw_fun` would become invalid. ```rust use dlopen2::symbor::Library; fn main(){ let raw_fun = { let lib = Library::open("libexample.dylib").unwrap(); let safe_fun = unsafe{ lib.symbol::f64>("some_symbol_name") }.unwrap(); *safe_fun }; //raw_fun is now a dangling symbol } ``` -------------------------------- ### Open a dynamic library Source: https://docs.rs/dlopen2/0.8.2/dlopen2/raw/struct.Library.html Demonstrates opening a library using either a full file path or just the file name. ```rust use dlopen2::raw::Library; fn main() { //use full path let lib = Library::open("/lib/i386-linux-gnu/libm.so.6").unwrap(); //use only file name let lib = Library::open("libm.so.6").unwrap(); } ``` -------------------------------- ### Dangling Symbol Prevention Example Source: https://docs.rs/dlopen2/0.8.2/dlopen2/symbor/index.html An example illustrating a potential mistake that could lead to a dangling symbol if the library handle is dropped before the borrowed symbol is no longer used. This emphasizes the importance of managing the library's lifetime. ```APIDOC ## GET /api/products ### Description Retrieves a list of all available products. ### Method GET ### Endpoint /api/products ### Parameters #### Path Parameters None #### Query Parameters - **category** (string) - Optional - Filters products by a specific category. - **limit** (integer) - Optional - Limits the number of products returned. - **offset** (integer) - Optional - Skips a specified number of products from the beginning of the result set. #### Request Body None ### Request Example ``` GET /api/products?category=electronics&limit=10&offset=0 HTTP/1.1 Host: example.com Accept: application/json ``` ### Response #### Success Response (200) - **products** (array) - A list of product objects. - **id** (string) - The unique identifier for the product. - **name** (string) - The name of the product. - **price** (number) - The price of the product. - **category** (string) - The category of the product. #### Response Example ```json { "products": [ { "id": "prod-abc", "name": "Laptop", "price": 1200.00, "category": "electronics" }, { "id": "prod-def", "name": "Keyboard", "price": 75.00, "category": "electronics" } ] } ``` ``` -------------------------------- ### Address Information Obtainer Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/raw/common.rs.html Shows how to use AddressInfoObtainer to get details about a symbol's address. ```APIDOC ## GET /api/users/{id} ### Description Retrieves the details of a specific user by their unique identifier. ### Method GET ### Endpoint /api/users/{id} ### Parameters #### Path Parameters - **id** (integer) - Required - The unique identifier of the user to retrieve. #### Query Parameters - **fields** (string) - Optional - A comma-separated list of fields to include in the response. ### Response #### Success Response (200) - **id** (integer) - The unique identifier for the user. - **username** (string) - The username of the user. - **email** (string) - The email address of the user. - **created_at** (string) - The timestamp when the user was created. #### Response Example ```json { "id": 123, "username": "johndoe", "email": "john.doe@example.com", "created_at": "2023-10-27T10:00:00Z" } ``` ``` -------------------------------- ### Get Symbol by Name (CString) Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/raw/common.rs.html Retrieves a symbol from the library using its name as a CString. This is a helper method for `symbol`. ```rust pub unsafe fn symbol(&self, name: &str) -> Result { unsafe { let cname = CString::new(name)?; self.symbol_cstr(cname.as_ref()) } } ``` -------------------------------- ### Dangling symbol mistake example Source: https://docs.rs/dlopen2/0.8.2/dlopen2/symbor/index.html Illustrates a common mistake where dereferencing a safe wrapper into a raw symbol results in a dangling pointer. ```rust use dlopen2::symbor::Library; fn main(){ let raw_fun = { let lib = Library::open("libexample.dylib").unwrap(); let safe_fun = unsafe{ lib.symbol::f64>("some_symbol_name") }.unwrap(); *safe_fun }; //raw_fun is now a dangling symbol } ``` -------------------------------- ### Get Mutable Reference to Library Symbol (CStr) Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/symbor/library.rs.html An alternative to `reference_mut()` that accepts a `CStr` for the symbol name. Useful when dealing with C-style strings. ```rust pub unsafe fn reference_mut_cstr(&mut self, name: &CStr) -> Result<&mut T, Error> { unsafe { self.lib.symbol_cstr(name) } } ``` -------------------------------- ### Get Const Reference to Library Symbol (CStr) Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/symbor/library.rs.html An alternative to `reference()` that accepts a `CStr` for the symbol name. Useful when dealing with C-style strings. ```rust pub unsafe fn reference_cstr(&self, name: &CStr) -> Result<&T, Error> { unsafe { self.lib.symbol_cstr(name) } } ``` -------------------------------- ### Load and use a dynamic library with Container Source: https://docs.rs/dlopen2/0.8.2/dlopen2/wrapper/index.html Demonstrates the safe way to load a library and access symbols using the Container struct to ensure proper memory management. ```rust use dlopen2::wrapper::{Container, WrapperApi}; #[derive(WrapperApi)] struct Example<'a> { do_something: extern "C" fn(), add_one: unsafe extern "C" fn (arg: i32) -> i32, global_count: &'a mut u32, } fn main () { let mut container: Container = unsafe { Container::load("libexample.dylib")}.unwrap(); container.do_something(); let _result = unsafe { container.add_one(5) }; *container.global_count_mut() += 1; //symbols are released together with library handle //this prevents dangling symbols drop(container); } ``` -------------------------------- ### Implement ToString for generic types Source: https://docs.rs/dlopen2/0.8.2/dlopen2/enum.Error.html Converts any type that implements the `Display` trait into a `String`. This is a common way to get a string representation of a value. ```rust fn to_string(&self) -> String ``` -------------------------------- ### dlopen2 Wrapper API Usage Source: https://docs.rs/dlopen2/0.8.2/dlopen2/wrapper/index.html Demonstrates the recommended way to use the dlopen2 wrapper API with a `Container` to ensure safe handling of dynamic libraries and their symbols. ```APIDOC ## dlopen2 Wrapper API Usage ### Description This example shows the correct and safe usage of the `dlopen2` wrapper API. It utilizes the `Container` struct to manage the dynamic library handle and its associated API, preventing dangling symbols by ensuring that the library and symbols are released together. ### Method N/A (This is a usage example, not a specific API endpoint) ### Endpoint N/A ### Parameters N/A ### Request Example ```rust use dlopen2::wrapper::{Container, WrapperApi}; #[derive(WrapperApi)] struct Example<'a> { do_something: extern "C" fn(), add_one: unsafe extern "C" fn (arg: i32) -> i32, global_count: &'a mut u32, } fn main () { let mut container: Container = unsafe { Container::load("libexample.dylib")}.unwrap(); container.do_something(); let _result = unsafe { container.add_one(5) }; *container.global_count_mut() += 1; // Symbols are released together with the library handle // This prevents dangling symbols drop(container); } ``` ### Response N/A (This is a usage example) ``` -------------------------------- ### Library::open_self Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/raw/common.rs.html Opens the main program executable as a library. ```APIDOC ## Library::open_self ### Description Opens the main program itself as a library, allowing a shared library to load symbols from the host process. ### Response #### Success Response (Result) - **Library** (struct) - A handle to the main program library. ``` -------------------------------- ### Library::open_with_flags Source: https://docs.rs/dlopen2/0.8.2/dlopen2/raw/struct.Library.html Opens a dynamic library with specific platform flags. ```APIDOC ## Library::open_with_flags ### Description Opens a dynamic library with optional flags, primarily impacting behavior on Unix-like platforms. ### Parameters #### Request Body - **name** (AsRef) - Required - The path or name of the library. - **flags** (Option) - Optional - Platform-specific loading flags. ### Request Example Library::open_with_flags("libm.so.6", None) ``` -------------------------------- ### Open a dynamic library with flags Source: https://docs.rs/dlopen2/0.8.2/dlopen2/raw/struct.Library.html Opens a library with platform-specific flags, currently impacting only unix-like systems. ```rust use dlopen2::raw::Library; fn main() { //use full path let lib = Library::open_with_flags("/lib/i386-linux-gnu/libm.so.6", None).unwrap(); //use only file name let lib = Library::open("libm.so.6").unwrap(); } ``` -------------------------------- ### Container::into_raw Source: https://docs.rs/dlopen2/0.8.2/dlopen2/symbor/struct.Container.html Returns the raw OS handle for the opened library. ```APIDOC ## [METHOD] into_raw ### Description Returns the raw OS handle for the opened library (HMODULE on Windows, *mut c_void on Unix). This is an unsafe operation and should be used only when necessary. ### Method Instance Method ### Response #### Success Response (Handle) - **Handle** (Handle) - The raw OS handle of the library. ``` -------------------------------- ### Add dlopen2 Dependency to Cargo.toml Source: https://docs.rs/dlopen2/0.8.2/dlopen2/index.html Shows how to add the dlopen2 crate as a dependency in your project's Cargo.toml file. ```toml [dependencies] dlopen2 = "0.8" ``` -------------------------------- ### Get Symbol by CStr Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/raw/common.rs.html Retrieves a symbol from the library using its name as a CStr. It includes a runtime check to ensure the type `T` has the same size as a pointer to prevent incorrect memory transmutations. ```rust pub unsafe fn symbol_cstr(&self, name: &CStr) -> Result { unsafe { //TODO: convert it to some kind of static assertion (not yet supported in Rust) //this comparison should be calculated by compiler at compilation time - zero cost if size_of::() != size_of::<*mut ()>() { panic!( "The type passed to dlopen2::Library::symbol() function has a different size than a \ pointer - cannot transmute" ); } let raw = get_sym(self.handle, name)?; if raw.is_null() { Err(Error::NullSymbol) } else { Ok(transmute_copy(&raw)) } } } ``` -------------------------------- ### Define and use a library API with WrapperApi Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/wrapper/api.rs.html Demonstrates defining a struct with the WrapperApi derive macro and loading it via Container. Manual wrappers are required for pointer types like c_char. ```rust use dlopen2::wrapper::{WrapperApi, Container}; use std::os::raw::{c_char}; use std::ffi::CStr; #[derive(WrapperApi)] struct Example<'a> { #[dlopen2_name="function"] do_something: extern "C" fn(), add_one: unsafe extern "C" fn (arg: i32) -> i32, global_count: &'a mut u32, c_string: * const c_char, #[dlopen2_allow_null] maybe_null_ptr: * const (), } //wrapper for c_string won't be generated, implement it here impl<'a> Example<'a> { pub fn c_string(&self) -> &CStr { unsafe {CStr::from_ptr(self.c_string)} } } fn main () { let mut cont: Container = unsafe { Container::load("libexample.dylib")}.unwrap(); cont.do_something(); let _result = unsafe { cont.add_one(5) }; *cont.global_count_mut() += 1; println!("C string: {}", cont.c_string().to_str().unwrap()) } ``` -------------------------------- ### Access Optional API (Constant) Source: https://docs.rs/dlopen2/0.8.2/dlopen2/wrapper/struct.OptionalContainer.html Get a constant reference to the optional API within the OptionalContainer. This method returns an Option containing the optional API if loaded, otherwise None. ```rust pub fn optional(&self) -> &Option ``` -------------------------------- ### API Overview Source: https://docs.rs/dlopen2/0.8.2/index.html Comparison of the available APIs provided by the rs_dlopen2 library. ```APIDOC ## API Comparison ### raw - **Description**: A low-level API providing full flexibility for custom dynamic link library handling. ### symbor - **Description**: A high-level, safe API that prevents dangling symbols by creating zero-cost structural wrappers using Rust's borrowing mechanism. ### wrapper - **Description**: A high-level, safe API that prevents dangling symbols by creating zero-cost functional wrappers, ensuring the library and its symbols are released together. ``` -------------------------------- ### Library::open Source: https://docs.rs/dlopen2/0.8.2/dlopen2/raw/struct.Library.html Opens a dynamic library using the provided file path or name. ```APIDOC ## Library::open ### Description Opens a dynamic library. Note that platform-specific search paths apply. ### Parameters #### Request Body - **name** (AsRef) - Required - The path or name of the dynamic library to open. ### Request Example Library::open("libm.so.6") ### Response #### Success Response (200) - **Library** (Result) - The opened library instance. ``` -------------------------------- ### Get Mutable Reference to Library Symbol Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/symbor/library.rs.html Use this method to obtain a mutable reference to statically allocated data within the loaded library. Requires the symbol name as a string slice. ```rust pub unsafe fn reference_mut(&mut self, name: &str) -> Result<&mut T, Error> { unsafe { self.lib.symbol(name) } } ``` -------------------------------- ### Container::load Source: https://docs.rs/dlopen2/0.8.2/dlopen2/symbor/struct.Container.html Opens a dynamic link library and loads symbols into a Container structure. ```APIDOC ## [METHOD] load ### Description Opens a dynamic link library and loads symbols. This is an unsafe operation. ### Method Static Method ### Parameters #### Path Parameters - **name** (AsRef) - Required - The path to the dynamic link library to load. ### Response #### Success Response (Result) - **Self** (Container) - The loaded container instance. #### Error Response - **Error** (Error) - Returns an error if the library could not be opened or symbols could not be loaded. ``` -------------------------------- ### Utilities Module Source: https://docs.rs/dlopen2/0.8.2/dlopen2 Provides general utilities for working with dynamic link libraries. ```APIDOC ## Utilities Module ### Description Utilities for working with dynamic link libraries. ### Modules - **utils**: Utilities for working with dynamic link libraries. ``` -------------------------------- ### Get Const Reference to Library Symbol Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/symbor/library.rs.html Use this method to obtain a const reference to statically allocated data within the loaded library. Requires the symbol name as a string slice. ```rust pub unsafe fn reference(&self, name: &str) -> Result<&T, Error> { unsafe { self.lib.symbol(name) } } ``` -------------------------------- ### Basic Symbol Loading Source: https://docs.rs/dlopen2/0.8.2/dlopen2/symbor/index.html Demonstrates how to open a dynamic library and safely retrieve a symbol using the `Library::symbol` method. It highlights the prevention of dangling symbols by keeping the library handle in scope. ```APIDOC ## POST /api/users ### Description This endpoint allows for the creation of new user accounts. ### Method POST ### Endpoint /api/users ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **username** (string) - Required - The desired username for the new account. - **email** (string) - Required - The email address for the new account. - **password** (string) - Required - The password for the new account. ### Request Example ```json { "username": "johndoe", "email": "john.doe@example.com", "password": "securepassword123" } ``` ### Response #### Success Response (201) - **id** (string) - The unique identifier for the newly created user. - **username** (string) - The username of the created user. - **email** (string) - The email address of the created user. #### Response Example ```json { "id": "user-12345", "username": "johndoe", "email": "john.doe@example.com" } ``` ``` -------------------------------- ### Access Optional API (Mutable) Source: https://docs.rs/dlopen2/0.8.2/dlopen2/wrapper/struct.OptionalContainer.html Get a mutable reference to the optional API within the OptionalContainer. This method returns a mutable Option containing the optional API if loaded, otherwise None. ```rust pub fn optional_mut(&mut self) -> &mut Option ``` -------------------------------- ### Initialize AddressInfoObtainer Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/raw/common.rs.html Initializes the AddressInfoObtainer, which is necessary before obtaining address information. This is typically called within `AddressInfoObtainer::new()`. ```rust pub fn new() -> AddressInfoObtainer { unsafe { addr_info_init() }; AddressInfoObtainer {} } ``` -------------------------------- ### Implement WrapperApi for Option Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/wrapper/option.rs.html This implementation allows a library to be loaded as an optional value. If the library or its symbols are not found, it returns `Ok(None)` instead of an error. ```rust use super::super::Error; use super::super::raw::Library; use super::api::WrapperApi; impl where T: WrapperApi, { unsafe fn load(lib: &Library) -> Result { unsafe { match T::load(lib) { Ok(val) => Ok(Some(val)), Err(_) => Ok(None), } } } } ``` -------------------------------- ### Implement WrapperApi for Option Source: https://docs.rs/dlopen2/0.8.2/dlopen2/wrapper/trait.WrapperApi.html The `dlopen2` crate provides an implementation of `WrapperApi` for `Option` where `T` also implements `WrapperApi`. This allows for optional loading of library APIs. ```rust impl WrapperApi for Option where T: WrapperApi, { // Required method unsafe fn load(lib: &Library) -> Result{ // Implementation details would go here, likely attempting to load T and returning Some(T) or None unimplemented!() } } ``` -------------------------------- ### Preventing Dangling Symbols with dlopen2 Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/symbor/mod.rs.html This example demonstrates how dlopen2's symbor module prevents dangling symbols by tying symbol lifetimes to the library's lifetime. Attempting to use a symbol after the library is dropped would result in a compile-time error. ```rust use dlopen2::symbor::Library; fn main(){ let lib = Library::open("libexample.dylib").unwrap(); let fun = unsafe{lib.symbol::f64>("some_symbol_name")}.unwrap(); println!("fun(1.0) = {}", unsafe{fun(1.0)}); //this would not compile because fun is a symbol borrowed from lib //drop(lib); } ``` -------------------------------- ### Load Library with Obligatory and Optional APIs Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/wrapper/optional.rs.html Use this function to load a dynamic library, attempting to load both the obligatory and optional APIs. The optional API will be `None` if its symbols are not found. ```rust pub unsafe fn load(name: S) -> Result, Error> where S: AsRef, { unsafe { let lib = Library::open(name)?; let api = Api::load(&lib)?; let optional = Optional::load(&lib).ok(); Ok(Self { lib, api, optional }) } } ``` -------------------------------- ### Library Opening API Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/symbor/library.rs.html Methods for opening dynamic link libraries, including the current program itself. ```APIDOC ## Library Opening API ### Description Provides methods to open dynamic link libraries. ### Methods #### `open(name: S) -> Result` Opens a dynamic link library using the provided file name or path. - **name** (S: AsRef) - The name or path of the library to open. #### `open_self() -> Result` Opens the program itself as a library. This allows a shared library to load symbols of the program it was loaded into. ``` -------------------------------- ### Load Dynamic Library with dlopen Flags Source: https://docs.rs/dlopen2/0.8.2/dlopen2/wrapper/struct.Container.html Loads a dynamic library using its file name or path, with the ability to specify flags used by `libc::dlopen`. This provides more control over how the library is loaded. ```rust pub unsafe fn load_with_flags( name: S, flags: Option, ) -> Result, Error> where S: AsRef, ``` -------------------------------- ### OptionalContainer::load Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/wrapper/optional.rs.html Opens a dynamic library and attempts to load both the obligatory and optional API symbols. ```APIDOC ## OptionalContainer::load ### Description Opens the library using the provided file name or path and loads all symbols. If the optional API symbols are found, they are loaded; otherwise, the optional API remains None. ### Parameters #### Path Parameters - **name** (AsRef) - Required - The file name or path to the dynamic library. ### Response - **Result, Error>** - Returns the container if successful, or an Error if the library or obligatory API could not be loaded. ``` -------------------------------- ### OptionalContainer Source: https://docs.rs/dlopen2/0.8.2/dlopen2/wrapper/struct.OptionalContainer.html Container for a library handle and both obligatory and optional APIs within a single structure. This allows for managing libraries that may have different API versions, where some versions include broader API sets than others. If symbols for the optional API are found, it gets loaded; otherwise, the `optional()` method returns `None`. ```APIDOC ## Struct OptionalContainer ### Summary ```rust pub struct OptionalContainer where Api: WrapperApi, Optional: WrapperApi, { /* private fields */ } ``` Available on **crate feature `wrapper`** only. ### Description Container for a library handle and both obligatory and optional APIs inside one structure. A common problem with dynamic link libraries is that they often have different versions and some of those versions have broader API than others. This structure allows you to use two APIs at the same time - one obligatory and one optional. If symbols of the optional API are found in the library, the optional API gets loaded. Otherwise the `optional()` method will return `None`. ### Example ```rust use dlopen2::wrapper::{OptionalContainer, WrapperApi}; #[derive(WrapperApi)] struct Obligatory<'a> { do_something: extern "C" fn(), global_count: &'a mut u32, } #[derive(WrapperApi)] struct Optional{ add_one: unsafe extern "C" fn (arg: i32) -> i32, c_string: * const u8 } fn main () { let mut container: OptionalContainer = unsafe { OptionalContainer::load("libexample.dylib") }.unwrap(); container.do_something(); *container.global_count_mut() += 1; match container.optional(){ &Some(ref opt) => { let _result = unsafe { opt.add_one(5) }; println!("First byte of C string is {}", unsafe {*opt.c_string}); }, &None => println!("The optional API was not loaded!") } } ``` **Note:** For more complex cases (multiple versions of API) you can use `WrapperMultiApi`. ``` -------------------------------- ### Load and use a symbol from a dynamic library Source: https://docs.rs/dlopen2/0.8.2/dlopen2/raw/index.html Demonstrates opening a library and retrieving a function symbol. Note that the returned function pointer becomes dangling once the library is dropped. ```rust use dlopen2::raw::Library; fn main(){ let lib = Library::open("libexample.so").unwrap(); let fun_add_one: unsafe extern "C" fn(i32)->i32 = unsafe{lib.symbol("add_one")}.unwrap(); println!("1+1= {}", unsafe{fun_add_one(1)}); drop(lib); //warning! fun_add_one is now a dangling symbol and use of it may crash your application. } ``` -------------------------------- ### platform_file_name Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/utils.rs.html Constructs a platform-specific dynamic library filename from a core name, automatically appending the correct prefix and extension based on the target operating system. ```APIDOC ## platform_file_name ### Description Generates a platform-specific file name for a dynamic library. For example, on Unix-based systems, it prepends 'lib' and appends '.so', while on Windows, it appends '.dll'. ### Parameters #### Arguments - **core_name** (AsRef) - Required - The base name of the library (e.g., 'example'). ### Response - **OsString** - The formatted platform-specific library filename. ``` -------------------------------- ### Open Dynamic Library by Name Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/symbor/library.rs.html Opens a dynamic link library using its file name or path. This is the primary method for loading external libraries. ```rust pub fn open(name: S) -> Result where S: AsRef, { Ok(Library { lib: RawLib::open(name)?, }) } ``` -------------------------------- ### Container::into_raw Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/symbor/container.rs.html Consumes the `Container` and returns the raw OS-specific handle of the opened dynamic library. This method should be used with extreme caution as it bypasses the `Container`'s management, potentially leading to use-after-free errors if not handled properly. ```APIDOC ## POST /container/into_raw ### Description Returns the raw operating system handle for the opened dynamic library. This method is `unsafe` because it exposes low-level details of the library handle (e.g., `HMODULE` on Windows, `*mut c_void` on Unix). Direct manipulation of this handle can lead to undefined behavior if not done correctly. It is recommended to use this method only when absolutely necessary. ### Method `POST` (Conceptual - this is a function call, not a typical HTTP endpoint) ### Endpoint `container.into_raw()` ### Parameters None ### Request Example ```rust use dlopen2::symbor::Container; // Assuming container is a valid Container instance // let raw_handle = unsafe { container.into_raw() }; ``` ### Response #### Success Response (200) * **raw::Handle** - The raw OS handle for the library. This is platform-dependent. #### Response Example ```rust // The type of raw_handle depends on the OS. // On Unix: *mut std::os::raw::c_void // On Windows: std::os::windows::raw::winapi::HMODULE ``` ``` -------------------------------- ### Container::load_with_flags Source: https://docs.rs/dlopen2/0.8.2/dlopen2/wrapper/struct.Container.html Opens a dynamic library with specific flags used by libc::dlopen. ```APIDOC ## unsafe fn load_with_flags(name: S, flags: Option) -> Result, Error> ### Description Same as load(), except specify flags used by libc::dlopen. ### Parameters #### Path Parameters - **name** (S: AsRef) - Required - The file name or path to the dynamic library. - **flags** (Option) - Optional - Flags to pass to the underlying dlopen call. ``` -------------------------------- ### Define PLATFORM_FILE_PREFIX Constant Source: https://docs.rs/dlopen2/0.8.2/dlopen2/utils/constant.PLATFORM_FILE_PREFIX.html This constant is available on Unix-only systems. It represents the conventional prefix for library files, such as 'lib' on Unix-based systems. Windows does not use this convention. ```rust pub const PLATFORM_FILE_PREFIX: &str = "lib"; ``` -------------------------------- ### Library Handle Management Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/symbor/library.rs.html Method for retrieving the raw OS handle of the library. ```APIDOC ## into_raw() ### Description Returns the raw OS handle for the opened library. This is HMODULE on Windows and *mut c_void on Unix systems. ### Response - **raw::Handle** - The raw OS handle of the library. ``` -------------------------------- ### Library Methods Source: https://docs.rs/dlopen2/0.8.2/dlopen2/symbor/struct.Library.html Methods for opening dynamic libraries and retrieving symbols, references, or pointers. ```APIDOC ## Library::open ### Description Opens a dynamic link library using the provided file name or path. ### Method Static Method ### Parameters #### Request Body - **name** (AsRef) - Required - The file name or path of the library to open. ### Response #### Success Response (200) - **Library** (Result) - The opened library handle. --- ## Library::symbol ### Description Obtain a symbol from the library. This is the most general method for obtaining functions and pointers. ### Method Instance Method (unsafe) ### Parameters #### Request Body - **name** (&str) - Required - The name of the symbol to retrieve. ### Response #### Success Response (200) - **Symbol** (Result, Error>) - The retrieved symbol. --- ## Library::reference ### Description Obtain a const reference to statically allocated data in the library. ### Method Instance Method (unsafe) ### Parameters #### Request Body - **name** (&str) - Required - The name of the data to reference. ### Response #### Success Response (200) - **Reference** (Result<&T, Error>) - A reference to the statically allocated data. ``` -------------------------------- ### Open Self as Library Source: https://docs.rs/dlopen2/0.8.2/src/dlopen2/raw/common.rs.html Opens the main program itself as a library. This is useful for shared libraries that need to access symbols from the program they are loaded into. ```rust use dlopen2::raw::Library; fn main() { let lib = Library::open_self().unwrap(); } ```