ffi. CLib

Represents a handle to a loaded shared library.

Example
const lib = dlopen(…);

lib.wrap(…);
lib.dlsym(…);

Methods

dlsym(name) → {CData|number}

Look up a symbol in the loaded library.

The dlsym() method retrieves a symbol (function, variable, or constant) from the loaded shared library or global symbol table.

Input patterns:

  1. Bare symbol name: Look up by symbol name directly. Returns a cdata pointer for functions/variables, or a number for constants.

  2. Full declaration: Provide a complete declaration string. The symbol name is extracted and used for lookup.

Parameters:
NameTypeDescription
namestring

The symbol name or full declaration string.

Throws: Error

Throws an exception if the symbol cannot be found or the declaration syntax is invalid.

Returns: CData | number

A cdata pointer for functions/variables, a number for constants, or null if the symbol cannot be resolved.

Examples
// Pattern 1: Bare symbol name
ffi.cdef('extern char **environ;');
let env = ffi.C.dlsym('environ');
print(env.get(0), "\n");
// Pattern 2: Full declaration
let getenv = ffi.C.dlsym('char *getenv(char *)');
print(ffi.string(getenv.deref('char *')));
// Access constant value (returns number)
ffi.cdef('const int INT_MAX;');
let max = ffi.C.dlsym('INT_MAX');  // => number

resolve(decl) → {CData}nullable

Resolve a symbol to a cdata pointer.

The resolve() method retrieves a symbol from the loaded library and returns a cdata pointer. Unlike wrap(), it does not create a callable wrapper - it returns the raw pointer for manual handling.

Parameters:
NameTypeDescription
declstring | CData

The function declaration or cdata function pointer.

Throws: Error

Throws an exception if the symbol cannot be resolved.

Returns: CData

A cdata pointer to the symbol, or null if resolution fails.

Example
// Resolve function pointer
ffi.cdef('int strcmp(const char *, const char *)');
let ptr = ffi.C.resolve('strcmp');
// ptr is a cdata, not callable directly

wrap(decl) → {function}nullable

Wrap a C function symbol into a callable ucode function.

The wrap() method retrieves a function symbol from the library and returns a callable wrapper that handles argument marshaling and function invocation via libffi.

Input patterns:

  1. Full declaration: Provide a complete function declaration string. The symbol name is extracted automatically.

  2. Bare symbol: Provide just the symbol name. Requires that the type was previously declared via cdef().

  3. cdata pointer: Provide a cdata containing a function pointer (e.g., from dlsym()). The type must match the cdata's type.

Parameters:
NameTypeDescription
declstring | CData

The function declaration string, bare symbol name, or cdata function pointer.

Throws: Error

Throws an exception if the symbol cannot be resolved or is not a function.

Returns: function

A callable function wrapper, or null if resolution fails.

Examples
// Pattern 1: Full declaration (no cdef needed)
let strcmp = ffi.C.wrap('int strcmp(const char *, const char *)');
print(strcmp("hello", "world"));  // => number (auto-converted)
// Pattern 2: Bare symbol (requires cdef)
ffi.cdef('int strcmp(const char *, const char *)');
let strcmp = ffi.C.wrap('strcmp');
print(strcmp("hello", "world"));  // => number (auto-converted)
// Pattern 3: cdata function pointer
ffi.cdef('size_t strlen(const char *)');
let strlen_sym = ffi.C.dlsym('strlen');
let strlen_fn = ffi.C.wrap(strlen_sym);
print(strlen_fn("hello"));  // => number (auto-converted)
// Pointer returns remain as cdata for explicit control
let getenv = ffi.C.wrap('char *getenv(char *)');
let path_ptr = getenv('PATH');  // => cdata (char*)
let path = ffi.string(path_ptr);  // Convert to ucode string