> ## 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

> 加載共享庫並獲取類型化函數定義

`dlopen` 加載共享庫並返回帶類型化符號的 [`Library`](/zh-Hant/api/library) 實例。

## 語法

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

## 示例

```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();
```

## 參數

| 參數        | 類型                            | 說明            |
| --------- | ----------------------------- | ------------- |
| `libName` | `string`                      | `.so` 庫的路徑或名稱 |
| `defs`    | `Record<string, FFIFunction>` | 函數名到類型定義的映射   |

## FFIFunction

```typescript theme={null}
interface FFIFunction {
  args: (string | StructSchema)[];  // 參數類型編碼，支持 StructSchema
  returns: string | StructSchema;   // 返回類型編碼，支持 StructSchema
  threadsafe?: boolean;             // 用於 JSCallback 定義
}
```

## 結構體類型支持

`args` 和 `returns` 除了接受 `FFIType.*` 字符串，還可傳入 `StructSchema` 實例，用於在寄存器中傳遞的小型 HFA 結構體。

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

const lib = dlopen('libfft.so', {
  complex_add: {
    args: [Complex, Complex],   // 展開為 4 個 double
    returns: Complex,           // 編碼為返回 buffer ← 返回指針
  },
});

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
```

內部流程：

```
defineFunction(handle, 'complex_add', 'dddd', '2')
                           ↑ StructSchema 展開為字段類型
調用時：
  ArrayBuffer → 解包為 [1, 2, 3, 4] → NAPI
  NAPI 返回 buffer → ffi.ptr(buf) → 指針返回給用戶
```

## 異步調用

每個 `symbols` 下的函數都掛載了 `.async` 方法，用於在工作線程上非阻塞調用：

```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);
});
```

對於基本返回類型，Promise 直接 resolve 值：

```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));
```

## 類型推斷

`dlopen` 使用 TypeScript 泛型推斷 `symbols` 的結構，爲所有定義的函數名提供 IDE 自動補全。

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

## 返回值

返回 [`Library`](/zh-Hant/api/library) 實例。
