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

# External Pre-built Libraries

> Integrate externally compiled .so libraries into arkffi

This guide demonstrates how to integrate a C/C++ library compiled externally (e.g., with CLion or CMake) into an arkffi project and call its functions via `dlopen`.

## Overview

1. Create a C/C++ library project
2. Cross-compile for HarmonyOS `arm64-v8a` using the NDK
3. Place the compiled `.so` into `entry/libs/arm64-v8a/`
4. Load and call it from ArkTS via `dlopen`

***

## 1. Create the External Library

**Source** `library.cpp`:

```c theme={null}
#ifdef __cplusplus
extern "C" {
#endif

    const char* hello(void) {
        return "Hello, World!";
    }

#ifdef __cplusplus
}
#endif
```

<Note>
  `extern "C"` prevents C++ name mangling, ensuring `dlsym("hello")` can find the symbol. Without it, the symbol would be mangled to `_Z5hellov` and `dlopen` would fail.
</Note>

**CMakeLists.txt**:

```cmake theme={null}
cmake_minimum_required(VERSION 3.3)
project(hello)
set(CMAKE_CXX_STANDARD 14)
add_library(hello SHARED library.cpp)
```

## 2. Cross-Compile for HarmonyOS

```bash theme={null}
export TOOLCHAIN=/path/to/ohos-sdk/native/llvm
export SYSROOT=/path/to/ohos-sdk/native/sysroot

$TOOLCHAIN/bin/aarch64-linux-ohos-clang++ \
  --sysroot=$SYSROOT \
  -fPIC -shared \
  -o libhello.so \
  library.cpp
```

## 3. Place the Output

```
entry/libs/arm64-v8a/libhello.so
```

<Note>
  If your project also supports `x86_64` emulator, place the corresponding `.so` under `entry/libs/x86_64/` as well.
</Note>

## 4. Configure abiFilters

Ensure `library/build-profile.json5` contains the target architecture in `abiFilters`:

```json theme={null}
{
  "buildOption": {
    "externalNativeOptions": {
      "path": "./src/main/cpp/CMakeLists.txt",
      "abiFilters": ["arm64-v8a"]
    }
  }
}
```

## 5. Call from ArkTS

```typescript theme={null}
import { dlopen, FFIType, CString, CFunction, JSCallback, Library } from 'arkffi';

const libhello = dlopen('libhello.so', {
  hello: { args: [], returns: FFIType.int64 },
});

const resultPtr = libhello.symbols.hello();
const resultStr = new CString(resultPtr);

console.log(resultStr.toString()); // -> "Hello, World!"

libhello.close();
```

### Important Notes

<Warning>
  * Functions returning `const char*` **must** use `returns: FFIType.int64` (to get the pointer), not `FFIType.CString`.
  * Use `CString` to read the actual string content from the pointer.
  * Ensure the library uses `extern "C"` to avoid name mangling.
</Warning>

## Troubleshooting

| Problem                          | Cause                           | Solution                                    |
| -------------------------------- | ------------------------------- | ------------------------------------------- |
| `dlsym failed: Symbol not found` | C++ name mangling               | Add `extern "C"` in source                  |
| `cannot locate library`          | `.so` not in correct path       | Check `entry/libs/${OHOS_ARCH}/` path       |
| `cannot locate symbol`           | Wrong toolchain for compilation | Use HarmonyOS NDK, not host system compiler |
| Call returns empty string        | Wrong return type               | Use `FFIType.int64`, not `FFIType.CString`  |
