> ## Documentation Index
> Fetch the complete documentation index at: https://docs.arkffi.hmbill.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# dlopen

> Load a shared library with typed function definitions

`dlopen` loads a shared library and returns a [`Library`](/en/api/library) instance with typed symbols.

## Syntax

```typescript theme={null}
function dlopen<Fns extends Record<string, FFIFunction>>(
  libName: string,
  defs: Fns,
): Library<Fns>;
```

## Example

```typescript theme={null}
import { dlopen, FFIType } from 'arkffi';

const lib = dlopen('libffi_target.so', {
  add:     { args: [FFIType.double, FFIType.double],     returns: FFIType.double },
  compute: { args: [FFIType.int32, FFIType.double, FFIType.CString], returns: FFIType.double },
});

lib.symbols.add(2.0, 3.0);
lib.symbols.compute(0, 4.0, 'square');
lib.close();
```

## Parameters

| Parameter | Type                          | Description                               |
| --------- | ----------------------------- | ----------------------------------------- |
| `libName` | `string`                      | Path or name of the `.so` library         |
| `defs`    | `Record<string, FFIFunction>` | Map of function names to type definitions |

## FFIFunction

```typescript theme={null}
interface FFIFunction {
  args: (string | StructSchema)[];  // Parameter type codes, supports StructSchema
  returns: string | StructSchema;   // Return type code, supports StructSchema
  threadsafe?: boolean;             // For JSCallback definitions
}
```

## Struct Type Support

`args` and `returns` accept `StructSchema` instances for small HFA structs passed in registers.

```typescript theme={null}
const Complex = Struct({ real: FFIType.double, imag: FFIType.double });

const lib = dlopen('libfft.so', {
  complex_add: {
    args: [Complex, Complex],   // expands to 4 doubles
    returns: Complex,            // encodes as '2' → returns buffer pointer
  },
});

let a = Complex.create({ real: 1, imag: 2 });
let b = Complex.create({ real: 3, imag: 4 });
let ptr: number = lib.symbols.complex_add(a, b);
let result = Complex.fromPtr(ptr);
console.log(result.real, result.imag); // 4, 6
```

Internally:

```
defineFunction(handle, 'complex_add', 'dddd', '2')
                           ↑ StructSchema expanded to field types
At call time:
  ArrayBuffer → unpacked as [1, 2, 3, 4] → NAPI
  NAPI returns buffer → ffi.ptr(buf) → pointer returned to user
```

## Async Calls

Each symbol has an `.async` method for non-blocking calls on a worker thread:

```typescript theme={null}
const Complex = Struct({ real: FFIType.double, imag: FFIType.double });
const lib = dlopen('libfft.so', {
  complex_mul: { args: [Complex, Complex], returns: Complex },
});

let a = Complex.create({ real: 4, imag: 1 });
let b = Complex.create({ real: 3, imag: 3 });
lib.symbols.complex_mul.async(a, b).then((ptr: number) => {
  let result = Complex.fromPtr(ptr);
  releasePtr(ptr);
});
```

For basic return types, the Promise resolves with the value directly:

```typescript theme={null}
const lib = dlopen('lib.so', {
  add: { args: [FFIType.double, FFIType.double], returns: FFIType.double },
});
lib.symbols.add.async(2.0, 3.0).then((r: number) => console.log(r));
```

## Type Inference

`dlopen` uses TypeScript generics to infer the shape of `symbols`, providing IDE autocompletion for all defined function names.

```typescript theme={null}
const lib = dlopen('lib.so', {
  myFunc: { args: [FFIType.double, FFIType.double], returns: FFIType.double },
});
lib.symbols.myFunc(2.0, 3.0); // autocompleted
```

## Return Value

Returns a [`Library`](/en/api/library) instance with typed `symbols`.
