IMPORTANT: To view this page as Markdown, append `.md` to the URL (e.g. /docs/manual/basics.md). For the complete Mojo documentation index, see llms.txt.
Skip to main content
Version: Nightly
For the complete Mojo documentation index, see llms.txt. Markdown versions of all pages are available by appending .md to any URL (e.g. /docs/manual/basics.md).

OwnedDLHandle

struct OwnedDLHandle

Represents an owned handle to a dynamically linked library with RAII semantics.

OwnedDLHandle owns the library handle and automatically calls dlclose() when the object is destroyed. This prevents resource leaks and double-free bugs.

Example usage:

from std.ffi import OwnedDLHandle

def main() raises:
var lib = OwnedDLHandle("libm.so")
var sqrt = lib.get_function[Float64]("sqrt")
print(sqrt(4.0)) # Prints: 2.0
# Library automatically closed when lib goes out of scope

Implemented traits

AnyType, Deinitable, Movable

Methods

__init__

def __init__(out self, flags: Int = Int(Int(256) if CompilationTarget.is_linux() else Int(8) or 2))

Initialize an owned handle to all global symbols in the current process.

Args:

  • flags (Int): The flags to load the dynamic library.

Raises:

If dlopen(nullptr, flags) fails.

def __init__[PathLike: PathLike, //](out self, path: PathLike, flags: Int = Int(Int(256) if CompilationTarget.is_linux() else Int(8) or 2))

Initialize an OwnedDLHandle by loading the dynamic library at the given path.

Parameters:

  • PathLike (PathLike): The type conforming to the os.PathLike trait.

Args:

  • path (PathLike): The path to the dynamic library file.
  • flags (Int): The flags to load the dynamic library.

Raises:

If dlopen(path, flags) fails.

__deinit__

def __deinit__(deinit self)

Unload the associated dynamic library.

This automatically calls dlclose() on the underlying library handle.

__bool__

def __bool__(self) -> Bool

Checks if the handle is valid.

Returns:

Bool: True if the handle is not null and False otherwise.

borrow

def borrow(self) -> _DLHandle

Returns a non-owning reference to this handle.

The returned _DLHandle does not own the library and should not be used after this OwnedDLHandle is destroyed.

Returns:

_DLHandle: A non-owning reference to the library handle.

check_symbol

def check_symbol(self, var name: String) -> Bool

Check that the symbol exists in the dynamic library.

Args:

  • name (String): The symbol to check.

Returns:

Bool: True if the symbol exists.

get_function

def get_function[return_type: RegisterPassable = NoneType](ref self, var name: String) -> _DLCallable[return_type, origin_of(self)]

Returns a callable for the function with the given name in the dynamic library.

The returned callable carries an immutable borrow of self, so the library cannot be dlclosed until after the callable is invoked. This prevents the dangling-function-pointer crash that would occur if the raw function pointer were returned directly and ASAP destruction ran dlclose between dlsym and the call.

Argument forwarding uses the C ABI (see the _DLCallable notes).

Missing symbols raise Error("symbol not found: ...") rather than aborting the process, so callers can probe for optional symbols.

Example:

from std.ffi import OwnedDLHandle

var lib = OwnedDLHandle("libm.so")
var sqrt = lib.get_function[Float64]("sqrt")
print(sqrt(4.0)) # 2.0

Parameters:

  • return_type (RegisterPassable): The return type of the underlying C function. Defaults to NoneType for void-returning functions.

Args:

  • name (String): The name of the function to get the handle for.

Returns:

_DLCallable[return_type, origin_of(self)]: A callable proxy that forwards to the resolved function and keeps the owning handle alive for the duration of each call.

Raises:

If the symbol cannot be resolved in the dynamic library.

get_symbol

def get_symbol[mut: Bool, origin: Origin[mut=mut], //, result_type: AnyType](ref[origin] self, name: StringSpan) -> Optional[Pointer[result_type, origin]]

Returns a pointer to the symbol with the given name in the dynamic library, or None if the symbol is not found.

The returned pointer borrows self, so the library cannot be dlclosed while the pointer is live. Its mutability follows the handle's: a symbol resolved through an immutable handle is read-only.

Example:

from std.ffi import OwnedDLHandle, c_int

var lib = OwnedDLHandle("libcounters.so")
var counter = lib.get_symbol[c_int]("live_connections")
if counter:
print(counter.value()[])

Parameters:

  • mut (Bool): The mutability of self.
  • origin (Origin[mut=mut]): The origin of self.
  • result_type (AnyType): The type of the symbol to return.

Args:

  • name (StringSpan): The name of the symbol to get the handle for.

Returns:

Optional[Pointer[result_type, origin]]: An optional pointer to the symbol, or None if not found.

def get_symbol[mut: Bool, origin: Origin[mut=mut], //, result_type: AnyType](ref[origin] self, *, cstr_name: CStringSlice) -> Optional[Pointer[result_type, origin]]

Returns a pointer to the symbol with the given name in the dynamic library, or None if the symbol is not found.

See the name overload for how the returned pointer's origin and mutability relate to the handle.

Parameters:

  • mut (Bool): The mutability of self.
  • origin (Origin[mut=mut]): The origin of self.
  • result_type (AnyType): The type of the symbol to return.

Args:

  • cstr_name (CStringSlice): The name of the symbol to get the handle for.

Returns:

Optional[Pointer[result_type, origin]]: An optional pointer to the symbol, or None if not found.

call

def call[name: StringSpan[ImmStaticOrigin], return_type: RegisterPassable = NoneType, *T: AnyType = *?](self, *args: *T.values) -> return_type

Call a function with any amount of arguments.

Parameters:

Args:

  • *args (*T.values): The arguments.

Returns:

return_type: The result.