### Load library with Library::open Source: https://context7.com/openbytedev/dlopen2/llms.txt Use the raw API to open a library and retrieve function or data symbols. Symbols become dangling if the library is dropped. ```rust use dlopen2::raw::Library; use std::os::raw::c_int; fn main() { // Open a dynamic library by path or name let lib = Library::open("libm.so.6").expect("Could not open library"); // Obtain a function symbol let add_one: unsafe extern "C" fn(c_int) -> c_int = unsafe { lib.symbol("add_one") }.unwrap(); // Call the function let result = unsafe { add_one(5) }; println!("5 + 1 = {}", result); // Obtain a reference to static data let static_value: &i32 = unsafe { lib.symbol("static_value") }.unwrap(); println!("Static value: {}", static_value); // Obtain a mutable reference let mutable_value: &mut i32 = unsafe { lib.symbol("mutable_value") }.unwrap(); *mutable_value = 42; // Library is automatically closed when dropped // WARNING: Any symbols obtained become dangling after drop } ``` -------------------------------- ### Load Symbols into Structure with dlopen2 Source: https://github.com/openbytedev/dlopen2/blob/master/README.md Demonstrates how to use the high-level API to load symbols from a dynamic library into a Rust struct. Requires defining a struct that mirrors the library's API and using the `WrapperApi` derive macro. Ensure the library file exists and symbols are correctly named. ```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) = &mut cont.example_reference_option { *example_reference = 5; } } ``` -------------------------------- ### Open host program with Library::open_self Source: https://context7.com/openbytedev/dlopen2/llms.txt Access symbols exported by the currently running executable. ```rust use dlopen2::raw::Library; fn main() { // Open the program itself as a library let lib = Library::open_self().expect("Could not open self"); // Now you can obtain symbols exported by the main program let program_func: fn() -> i32 = unsafe { lib.symbol("exported_function") }.unwrap(); let result = program_func(); println!("Result from program function: {}", result); } ``` -------------------------------- ### Symbor API Library Usage Source: https://context7.com/openbytedev/dlopen2/llms.txt Demonstrates loading a library and accessing symbols using the Symbor API, which enforces borrowing rules at compile time. ```rust use dlopen2::symbor::Library; use std::os::raw::c_int; fn main() { let mut lib = Library::open("libexample.so").expect("Could not open library"); // Obtain a function symbol - returns a Symbol wrapper that borrows from lib let func = unsafe { lib.symbol:: c_int>("add_two") }.unwrap(); println!("2 + 2 = {}", unsafe { func(2) }); // Obtain a const reference to static data let const_ref: &i32 = unsafe { lib.reference("static_value") }.unwrap(); println!("Const value: {}", const_ref); // Obtain a mutable reference let mut_ref: &mut i32 = unsafe { lib.reference_mut("mutable_value") }.unwrap(); *mut_ref = 100; // Obtain a pointer that may be null let ptr_or_null = unsafe { lib.ptr_or_null::<() >("optional_ptr") }.unwrap(); println!("Pointer is null: {}", ptr_or_null.is_null()); // This would NOT compile - func borrows lib: // drop(lib); // Error: cannot move out of `lib` because it is borrowed } ``` -------------------------------- ### Raw API - Library::open_with_flags Source: https://context7.com/openbytedev/dlopen2/llms.txt Opens a dynamic library with custom dlopen flags, providing fine-grained control over symbol resolution behavior. This is primarily useful on Unix-like systems. ```APIDOC ## PUT /api/users/{userId} ### Description Updates an existing user's information. ### Method PUT ### Endpoint /api/users/{userId} ### Parameters #### Path Parameters - **userId** (string) - Required - The ID of the user to update. #### Request Body - **username** (string) - Optional - The new username. - **email** (string) - Optional - The new email address. ### Request Example ```json { "email": "john.doe.updated@example.com" } ``` ### Response #### Success Response (200) - **id** (string) - The unique identifier of the updated user. - **username** (string) - The updated username. - **email** (string) - The updated email address. #### Response Example ```json { "id": "user123", "username": "johndoe", "email": "john.doe.updated@example.com" } ``` ``` -------------------------------- ### Raw API - Library::open Source: https://context7.com/openbytedev/dlopen2/llms.txt Opens a dynamic library by its path or name and allows obtaining symbols (functions, references, pointers). Manual lifetime management is required, and symbols become dangling after the library is dropped. ```APIDOC ## POST /api/users ### Description Opens a dynamic library by path or name and obtains symbols. ### Method POST ### Endpoint /api/users ### Parameters #### Path Parameters - **userId** (string) - Required - The ID of the user to retrieve. #### Query Parameters - **include_details** (boolean) - Optional - Whether to include detailed user information. ### Request Body - **username** (string) - Required - The username for the new user. - **email** (string) - Required - The email address for the new user. ### Request Example ```json { "username": "johndoe", "email": "john.doe@example.com" } ``` ### Response #### Success Response (200) - **id** (string) - The unique identifier of the created user. - **username** (string) - The username of the user. - **email** (string) - The email address of the user. #### Response Example ```json { "id": "user123", "username": "johndoe", "email": "john.doe@example.com" } ``` ``` -------------------------------- ### Load library with custom flags Source: https://context7.com/openbytedev/dlopen2/llms.txt Apply platform-specific flags during library loading for fine-grained control over symbol resolution. ```rust use dlopen2::raw::Library; fn main() { // Open with custom flags (e.g., RTLD_LAZY | RTLD_LOCAL on Unix) let flags = Some(libc::RTLD_LAZY | libc::RTLD_LOCAL); let lib = Library::open_with_flags("libexample.so", flags) .expect("Could not open library with flags"); let func: fn() = unsafe { lib.symbol("my_function") }.unwrap(); func(); } ``` -------------------------------- ### Add dlopen2 Dependency to Cargo.toml Source: https://github.com/openbytedev/dlopen2/blob/master/README.md Specifies the necessary dependency to include the dlopen2 library in your Rust project. Add this to the `[dependencies]` section of your Cargo.toml file. ```toml [dependencies] dlopen2 = "0.8" ``` -------------------------------- ### WrapperMultiApi for Multiple API Versions Source: https://context7.com/openbytedev/dlopen2/llms.txt Handles multiple optional API subsets for libraries with varying feature sets across versions. Use WrapperMultiApi to combine required and optional API subsets. ```rust use dlopen2::wrapper::{Container, WrapperApi, WrapperMultiApi}; use std::os::raw::c_int; // Core API - always required #[derive(WrapperApi)] struct CoreApi<'a> { version: &'a i32, init: fn() -> bool, shutdown: fn(), } // Extended API - optional, may not exist in older versions #[derive(WrapperApi)] struct ExtendedApi<'a> { advanced_feature: fn(param: i32) -> i32, extra_data: &'a f64, } // Experimental API - optional, for beta versions #[derive(WrapperApi)] struct ExperimentalApi<'a> { beta_function: unsafe extern "C" fn() -> c_int, debug_value: &'a mut i32, } // Combined multi-API wrapper #[derive(WrapperMultiApi)] struct FullApi<'a> { // Required - loading fails if not present pub core: CoreApi<'a>, // Optional - None if symbols not found pub extended: Option>, pub experimental: Option>, } fn main() { let api: Container = unsafe { Container::load("libmyapp.so") }.expect("Could not load core API"); // Core API is always available println!("Library version: {}", api.core.version()); api.core.init(); // Check for extended features match &api.extended { Some(ext) => { println!("Extended API available!"); let result = ext.advanced_feature(42); println!("Advanced feature result: {}", result); println!("Extra data: {}", ext.extra_data()); } None => println!("Extended API not available in this version"), } // Check for experimental features if let Some(ref exp) = api.experimental { println!("Experimental features available!"); let result = unsafe { exp.beta_function() }; println!("Beta function result: {}", result); } api.core.shutdown(); } ``` -------------------------------- ### Raw API - Library::open_self Source: https://context7.com/openbytedev/dlopen2/llms.txt Opens the main program itself as a library, enabling shared libraries to load symbols from the host program. This is useful for scenarios where a dynamic library needs to call back into the main application. ```APIDOC ## GET /api/users/{userId} ### Description Retrieves a specific user's information. ### Method GET ### Endpoint /api/users/{userId} ### Parameters #### Path Parameters - **userId** (string) - Required - The ID of the user to retrieve. #### Query Parameters - **include_details** (boolean) - Optional - Whether to include detailed user information. ### Request Example ``` GET /api/users/user123?include_details=true ``` ### Response #### Success Response (200) - **id** (string) - The unique identifier of the user. - **username** (string) - The username of the user. - **email** (string) - The email address of the user. - **details** (object) - Optional - Additional user details if `include_details` is true. #### Response Example ```json { "id": "user123", "username": "johndoe", "email": "john.doe@example.com", "details": { "firstName": "John", "lastName": "Doe" } } ``` ``` -------------------------------- ### Retrieve symbol metadata with AddressInfoObtainer Source: https://context7.com/openbytedev/dlopen2/llms.txt Inspect library paths and base addresses for loaded symbols. ```rust use dlopen2::raw::{AddressInfoObtainer, Library}; use std::os::raw::c_int; fn main() { let lib = Library::open("libexample.so").expect("Could not open library"); let func: unsafe extern "C" fn(c_int) -> c_int = unsafe { lib.symbol("add_two") }.unwrap(); // Create an address info obtainer let aio = AddressInfoObtainer::new(); // Get information about the symbol's address let addr_info = unsafe { aio.obtain(func as *const ()) }.unwrap(); println!("Library path: {}", addr_info.dll_path); println!("Library base address: {:?}", addr_info.dll_base_addr); // Check for overlapping symbol information if let Some(symbol) = addr_info.overlapping_symbol { println!("Symbol name: {}", symbol.name); println!("Symbol address: {:?}", symbol.addr); } } ``` -------------------------------- ### Wrapper API Container Usage Source: https://context7.com/openbytedev/dlopen2/llms.txt Encapsulates a library and its symbols into a Container, which automatically generates safe accessor methods. ```rust use dlopen2::wrapper::{Container, WrapperApi}; use std::os::raw::c_int; #[derive(WrapperApi)] struct GameApi<'a> { // Safe Rust function init_game: fn() -> bool, // Unsafe C function update_frame: unsafe extern "C" fn(delta: f32), // Reference to static data (generates getter method) player_score: &'a i32, // Mutable reference (generates getter and getter_mut methods) player_health: &'a mut i32, // Optional function - returns Some(result) if present save_game: Option bool>, // Optional reference high_score: Option<&'a i32>, } fn main() { // Container loads library and all symbols together let mut game: Container = unsafe { Container::load("libgame.so") }.expect("Could not open library or load symbols"); // Call functions directly through container if game.init_game() { println!("Game initialized!"); } // Unsafe functions still require unsafe block unsafe { game.update_frame(0.016) }; // Access references via generated methods println!("Score: {}", game.player_score()); // Modify mutable references via _mut methods *game.player_health_mut() -= 10; println!("Health: {}", game.player_health()); // Optional functions return Option if let Some(saved) = game.save_game(1) { println!("Game saved: {}", saved); } // Container ensures symbols and library are released together // No dangling symbols possible } ``` -------------------------------- ### Raw API - AddressInfoObtainer Source: https://context7.com/openbytedev/dlopen2/llms.txt Retrieves metadata about symbols loaded from dynamic libraries, including the library path and symbol address information. It can also detect overlapping symbol information. ```APIDOC ## DELETE /api/users/{userId} ### Description Deletes a specific user. ### Method DELETE ### Endpoint /api/users/{userId} ### Parameters #### Path Parameters - **userId** (string) - Required - The ID of the user to delete. ### Response #### Success Response (204) No content is returned upon successful deletion. #### Response Example (No content) ``` -------------------------------- ### Container::load_self for Host API Access Source: https://context7.com/openbytedev/dlopen2/llms.txt Loads symbols from the current program itself, useful for plugin systems where plugins need to call back into the host. Use Container::load_self to access symbols from the current executable. ```rust use dlopen2::wrapper::{Container, WrapperApi}; #[derive(WrapperApi)] struct HostApi<'a> { host_log: fn(message: &str), host_version: &'a i32, } fn main() { // Load API from the program itself let host: Container = unsafe { Container::load_self() }.expect("Could not load host API"); host.host_log("Plugin initialized"); println!("Host version: {}", host.host_version()); } ``` -------------------------------- ### Error Handling with dlopen2::Error Source: https://context7.com/openbytedev/dlopen2/llms.txt The library provides comprehensive error handling through the Error enum for all API levels. Handle library opening and symbol loading errors using the Error enum. ```rust use dlopen2::raw::Library; use dlopen2::Error; fn main() { // Handle library opening errors let lib = match Library::open("nonexistent.so") { Ok(lib) => lib, Err(Error::OpeningLibraryError(io_err)) => { eprintln!("Failed to open library: {}", io_err); return; } Err(e) => { eprintln!("Unexpected error: {}", e); return; } }; // Handle symbol loading errors let func: Result = unsafe { lib.symbol("missing_func") }; match func { Ok(f) => f(), Err(Error::SymbolGettingError(io_err)) => { eprintln!("Symbol not found: {}", io_err); } Err(Error::NullSymbol) => { eprintln!("Symbol exists but has null value"); } Err(Error::NullCharacter(nul_err)) => { eprintln!("Invalid symbol name: {}", nul_err); } Err(e) => { eprintln!("Other error: {}", e); } } } ``` -------------------------------- ### SymBorApi Derive Macro Usage Source: https://context7.com/openbytedev/dlopen2/llms.txt Uses the SymBorApi derive macro to load multiple symbols into a struct, reducing boilerplate for complex library interfaces. ```rust use dlopen2::symbor::{Library, PtrOrNull, Ref, RefMut, SymBorApi, Symbol}; use std::os::raw::{c_char, c_int}; #[derive(SymBorApi)] struct MathApi<'a> { // Function symbols pub add: Symbol<'a, fn(i32, i32) -> i32>, pub multiply: Symbol<'a, unsafe extern "C" fn(c_int, c_int) -> c_int>, // Reference to static data pub pi_value: Ref<'a, f64>, // Mutable reference pub counter: RefMut<'a, i32>, // Pointer that accepts null values pub optional_data: PtrOrNull<'a, c_char>, // Optional symbol - None if not found in library pub optional_func: Option bool>>, // Custom symbol name using attribute #[dlopen2_name = "internal_add"] pub aliased_add: Symbol<'a, fn(i32, i32) -> i32>, } fn main() { let lib = Library::open("libmath.so").expect("Could not open library"); let mut api = unsafe { MathApi::load(&lib) }.expect("Could not load API"); // Use loaded symbols directly let sum = (api.add)(5, 3); println!("5 + 3 = {}", sum); let product = unsafe { (api.multiply)(4, 7) }; println!("4 * 7 = {}", product); println!("Pi value: {}", *api.pi_value); *api.counter += 1; println!("Counter: {}", *api.counter); // Handle optional symbols match api.optional_func { Some(func) => println!("Optional function result: {}", func()), None => println!("Optional function not available"), } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.