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

# Async Calls

> Call native C functions without blocking the JS thread

## Sync vs Async

arkffi's default C function calls are **synchronous** — `lib.symbols.add(2.0, 3.0)` blocks the current thread until the function returns.

For expensive operations (complex computation, I/O), use **`callAsync`** to offload the call to a libuv worker thread and get a Promise back.

## `ffi.callAsync`

```typescript theme={null}
import ffi from 'liblibrary.so';

const handle = ffi.load('libffi_target.so');
ffi.defineFunction(handle, 'factorial', 'i', 'l');

ffi.callAsync(handle, 'factorial', 'i', 'l', [10], []).then((r: number) => {
  console.log(r); // 3628800
  ffi.close(handle);
});
```

### Syntax

```typescript theme={null}
function callAsync(
  handle: bigint,
  funcName: string,
  argTypes: string,
  returnType: string,
  numArgs: number[],
  strArgs: string[],
): Promise<number>;
```

### Parameters

| Parameter    | Type       | Description                                             |
| ------------ | ---------- | ------------------------------------------------------- |
| `handle`     | `bigint`   | Library handle from `ffi.load()`                        |
| `funcName`   | `string`   | Function name (must be registered via `defineFunction`) |
| `argTypes`   | `string`   | Argument type codes                                     |
| `returnType` | `string`   | Return type code                                        |
| `numArgs`    | `number[]` | Numeric arguments                                       |
| `strArgs`    | `string[]` | String arguments                                        |

## `AsyncCFunction`

`AsyncCFunction` is the async counterpart of `CFunction` with the same signature, returning `Promise<number>`. No `defineFunction` needed — works directly with function pointers:

```typescript theme={null}
import { AsyncCFunction, FFIType } from 'arkffi';
import ffi from 'liblibrary.so';

const handle = ffi.load('libffi_target.so');
const addPtr = ffi.getSymbolPtr(handle, 'add');

const asyncAdd = AsyncCFunction({
  args: [FFIType.double, FFIType.double],
  returns: FFIType.double,
  ptr: addPtr,
});

asyncAdd(2.0, 3.0).then((r: number) => {
  console.log(r); // 5.0
});

Promise.all([asyncAdd(1.0, 2.0), asyncAdd(3.0, 4.0)]).then((results) => {
  console.log(results); // [3.0, 7.0]
});

asyncAdd.close();
ffi.close(handle);
```

### Comparison

| Feature                | `CFunction`     | `AsyncCFunction`          |
| ---------------------- | --------------- | ------------------------- |
| Returns                | `number` (sync) | `Promise<number>` (async) |
| Blocks main thread     | ✅ Yes           | ❌ No                      |
| Needs `defineFunction` | ❌ No            | ❌ No                      |
| Type support           | All             | All                       |
| Close method           | `.close()`      | `.close()`                |

## Usage with `dlopen`

```typescript theme={null}
const Complex = Struct({
  real: FFIType.double,
  imag: FFIType.double,
});
const LibFFT = dlopen(LIB_NAME_FFT, {
  complex_new: { args: [FFIType.double, FFIType.double], returns: Complex },
  complex_add: { args: [Complex, Complex], returns: Complex },
  complex_sub: { args: [Complex, Complex], returns: Complex },
  complex_mul: { args: [Complex, Complex], returns: Complex },
  fft: { args: [FFIType.ptr, FFIType.int32], returns: FFIType.void }
});

let a = Complex.create({ real: 4, imag: 1 });
let b = Complex.create({ real: 3, imag: 3 });
LibFFT.symbols.complex_mul.async(a, b)
  .then((mulPtr) => {
    let mulVal = Complex.fromPtr(mulPtr);
    console.log('complex_mul', mulVal.real, mulVal.imag);
  })
  .finally(() => {
    LibFFT.close();
  });
console.log('LibFFT.symbols.complex_mul.async');
```

## Implementation

1. `callAsync` parses arguments on the JS thread and creates a `napi_async_work`
2. The worker thread executes `DispatchCallRaw` — a pure C function pointer call with no NAPI involvement
3. On completion, the Promise is resolved on the JS thread
4. The JS main thread is never blocked

## Limitations

* String return types are not supported (no async version of `callString`)
* Callbacks (`JSCallback`) cannot be invoked from the async worker thread
* The function must be registered via `defineFunction` first
