Skip to content

集成指南

版本: 1.0.3
平台: Android arm64-v8a / Linux aarch64
交付形式: libacl.a + include/acl/ + license.dat

本页只保留客户接入时真正需要的步骤: 复制文件、链接静态库、初始化 License、调用第一个算子。

1. 准备文件

把 SDK zip 里的文件放进你的工程。目录名可以按项目习惯调整,但推荐保持下面的结构。

Android arm64-v8a:

text
your_project/
  include/acl/
    acl.h
    api.h
    err.h
    typeDef.h
  lib/arm64-v8a/
    libacl.a
  license.dat

Linux aarch64:

text
your_project/
  include/acl/
    acl.h
    api.h
    err.h
    typeDef.h
  lib/linux-aarch64/
    libacl.a
  license.dat

Trial zip 会额外带 include/acl/trial/api.hppinclude/acl/trial/watermark.h。客户代码通常只需要 #include <acl/api.h>;只有想显式使用 Trial 专用声明时才 include <acl/trial/api.hpp>

2. 配置构建

Android CMake

cmake
cmake_minimum_required(VERSION 3.10)
project(your_app)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_library(acl STATIC IMPORTED)
set_target_properties(acl PROPERTIES
    IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lib/${ANDROID_ABI}/libacl.a
)

add_library(your_app SHARED your_app.cpp)
target_include_directories(your_app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(your_app acl m log atomic z)

Android 只支持 arm64-v8a。如果用 Android.mk,核心配置如下:

makefile
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := acl
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libacl.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := your_app
LOCAL_SRC_FILES := your_app.cpp
LOCAL_STATIC_LIBRARIES := acl
LOCAL_LDLIBS := -lm -llog -latomic -lz
include $(BUILD_SHARED_LIBRARY)

Linux aarch64 CMake

先准备 toolchain 文件,例如 toolchains/linux-aarch64.cmake:

cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_C_COMPILER   aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
set(CMAKE_AR           aarch64-linux-gnu-ar)
set(CMAKE_RANLIB       aarch64-linux-gnu-ranlib)
add_compile_options(-march=armv8-a)

CMakeLists.txt:

cmake
cmake_minimum_required(VERSION 3.10)
project(your_app)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_library(acl STATIC IMPORTED)
set_target_properties(acl PROPERTIES
    IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lib/linux-aarch64/libacl.a
)

add_executable(your_app your_app.cpp)
target_include_directories(your_app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(your_app acl m pthread)

构建:

bash
cmake -DCMAKE_TOOLCHAIN_FILE=toolchains/linux-aarch64.cmake -DCMAKE_BUILD_TYPE=Release -S . -B build
cmake --build build -j

不用 CMake 时也可以直接交叉编译:

bash
aarch64-linux-gnu-g++ -O2 -std=c++17 -Iinclude \
    -o your_app your_app.cpp lib/linux-aarch64/libacl.a \
    -lm -lpthread

3. 初始化 License

调用任何算子前,先调用一次 acl::init()。必须传入设备上 license.dat 的真实路径。

cpp
#include <acl/acl.h>

int ret = acl::init("/path/to/license.dat");
if (ret != 0) {
    // 处理错误码,见下方表格
}

Android 上不要硬编码 /data/data/...。建议首次启动时把 APK assets 里的 license.dat 复制到 Context.getFilesDir(),再把绝对路径传给 native:

java
File licenseFile = new File(context.getFilesDir(), "license.dat");
int ret = nativeInitAcl(licenseFile.getAbsolutePath());

JNI 侧只需要把字符串转成 C 字符串:

cpp
#include <jni.h>
#include <acl/acl.h>

extern "C" JNIEXPORT jint JNICALL
Java_com_yourapp_AclLicense_nativeInitAcl(JNIEnv* env, jclass,
                                           jstring licensePath) {
    const char* path = env->GetStringUTFChars(licensePath, nullptr);
    int ret = acl::init(path);
    env->ReleaseStringUTFChars(licensePath, path);
    return ret;
}

更多 License 送达、续费补发、tier 匹配规则见 License 接入指南

4. 调用第一个算子

Starter / Pro / Business 使用通用 API。所有公开算子声明都在 <acl/api.h> 中:

cpp
#include <acl/acl.h>
#include <acl/api.h>
#include <cstdint>

int main() {
    int ret = acl::init("license.dat");
    if (ret != 0) return ret;

    const int width = 1920;
    const int height = 1280;

    uint8_t* src = new uint8_t[width * height];
    uint8_t* dst = new uint8_t[width * height];

    // stride 传 0 表示连续内存,库按 width * channels * sizeof(T) 计算。
    ret = acl::neon::filter::gaussianBlur(
        src, dst,
        width, height,
        /*srcStride=*/0, /*dstStride=*/0,
        /*kRadiusX=*/2, /*kRadiusY=*/2,
        /*sigmaX=*/1.0, /*sigmaY=*/1.0);

    delete[] src;
    delete[] dst;
    return ret;
}

常用命名空间:

  • acl::neon::{module}::op(...): ARM NEON 加速版本,推荐在 ARM64 上优先使用
  • acl::{module}::op(...): C++ scalar 版本,适合作为功能等价路径或更宽类型支持路径

3 通道图像通常通过 cn=3 参数传入。少数 NEON 滤波算子有独立 _3ch 快速入口,例如 gaussianBlur3x3_3chgaussianBlur5x5_3chmedianFilter3x3_3ch。完整列表以 API 参考 为准。

Trial 注意事项

Trial 不是通用 API。它只提供 2 个固定参数入口:

  • acl::trial::resizeBilinear2xDown_cpp
  • acl::trial::resizeBilinear2xDown_neon

Trial 输入固定为 1920x1280uint8_t、单通道、连续内存。2x 下采样输出为 960x640。输出会带 "ACL Pack Trial" 水印。

cpp
#include <acl/acl.h>
#include <acl/api.h>
#include <cstdint>

uint8_t* src = /* 1920x1280 */;
uint8_t* dst = /* 960x640 */;

int ret = acl::init("license.dat");
if (ret == 0) {
    ret = acl::trial::resizeBilinear2xDown_neon(src, dst);
}

错误码

代码含义
0ACL_OK成功
-1ACL_ERR_GENERIC未分类失败
-2ACL_ERR_INVAL参数无效,例如空指针、尺寸错误、枚举越界
-3ACL_ERR_NOMEM内存不足或临时工作区分配失败
-4ACL_ERR_NOSUP当前类型或参数组合不支持
-5ACL_ERR_IO文件或 I/O 失败
-1001ACL_ERR_LICENSE_INVALIDLicense 文件缺失、损坏、签名失败,或尚未成功初始化
-1005ACL_ERR_NOT_LICENSEDLicense tier 与库不匹配,或当前 tier 不包含该算子
-1006ACL_ERR_RESOLUTION_LIMITTrial 输入尺寸不符合固定要求

常见问题

现象处理方式
acl/acl.h: No such file检查 include 路径是否指向 include/
undefined reference to acl::init确认链接了同一个 zip 里的 libacl.a
Android 链接 __android_log_print__atomic_*zlib 相关符号失败链接 log atomic z
Linux 链接 pthread_* 失败链接 pthread
每个算子都返回 -1001检查 acl::init() 是否先调用且返回 0
acl::init() 返回 -1005license.datlibacl.a 不是同一 tier 或同一交付包

内存和 stride

  • 输入和输出图像 buffer 由客户分配和释放。
  • stride 单位是字节,不是像素。
  • 连续内存可以传 0;非连续内存请传真实行跨度。
  • 对连续图像,最小 stride 是 width * channels * sizeof(T)
  • 部分算子会分配内部临时工作区;如果分配失败会返回 ACL_ERR_NOMEM

下一步: 查看 API 参考算子 tier 列表