集成指南
版本: 1.0.3
平台: Android arm64-v8a / Linux aarch64
交付形式: libacl.a + include/acl/ + license.dat
本页只保留客户接入时真正需要的步骤: 复制文件、链接静态库、初始化 License、调用第一个算子。
1. 准备文件
把 SDK zip 里的文件放进你的工程。目录名可以按项目习惯调整,但推荐保持下面的结构。
Android arm64-v8a:
your_project/
include/acl/
acl.h
api.h
err.h
typeDef.h
lib/arm64-v8a/
libacl.a
license.datLinux aarch64:
your_project/
include/acl/
acl.h
api.h
err.h
typeDef.h
lib/linux-aarch64/
libacl.a
license.datTrial zip 会额外带 include/acl/trial/api.hpp 和 include/acl/trial/watermark.h。客户代码通常只需要 #include <acl/api.h>;只有想显式使用 Trial 专用声明时才 include <acl/trial/api.hpp>。
2. 配置构建
Android 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,核心配置如下:
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:
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_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)构建:
cmake -DCMAKE_TOOLCHAIN_FILE=toolchains/linux-aarch64.cmake -DCMAKE_BUILD_TYPE=Release -S . -B build
cmake --build build -j不用 CMake 时也可以直接交叉编译:
aarch64-linux-gnu-g++ -O2 -std=c++17 -Iinclude \
-o your_app your_app.cpp lib/linux-aarch64/libacl.a \
-lm -lpthread3. 初始化 License
调用任何算子前,先调用一次 acl::init()。必须传入设备上 license.dat 的真实路径。
#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:
File licenseFile = new File(context.getFilesDir(), "license.dat");
int ret = nativeInitAcl(licenseFile.getAbsolutePath());JNI 侧只需要把字符串转成 C 字符串:
#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> 中:
#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_3ch、gaussianBlur5x5_3ch、medianFilter3x3_3ch。完整列表以 API 参考 为准。
Trial 注意事项
Trial 不是通用 API。它只提供 2 个固定参数入口:
acl::trial::resizeBilinear2xDown_cppacl::trial::resizeBilinear2xDown_neon
Trial 输入固定为 1920x1280、uint8_t、单通道、连续内存。2x 下采样输出为 960x640。输出会带 "ACL Pack Trial" 水印。
#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);
}错误码
| 代码 | 宏 | 含义 |
|---|---|---|
0 | ACL_OK | 成功 |
-1 | ACL_ERR_GENERIC | 未分类失败 |
-2 | ACL_ERR_INVAL | 参数无效,例如空指针、尺寸错误、枚举越界 |
-3 | ACL_ERR_NOMEM | 内存不足或临时工作区分配失败 |
-4 | ACL_ERR_NOSUP | 当前类型或参数组合不支持 |
-5 | ACL_ERR_IO | 文件或 I/O 失败 |
-1001 | ACL_ERR_LICENSE_INVALID | License 文件缺失、损坏、签名失败,或尚未成功初始化 |
-1005 | ACL_ERR_NOT_LICENSED | License tier 与库不匹配,或当前 tier 不包含该算子 |
-1006 | ACL_ERR_RESOLUTION_LIMIT | Trial 输入尺寸不符合固定要求 |
常见问题
| 现象 | 处理方式 |
|---|---|
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() 返回 -1005 | license.dat 和 libacl.a 不是同一 tier 或同一交付包 |
内存和 stride
- 输入和输出图像 buffer 由客户分配和释放。
stride单位是字节,不是像素。- 连续内存可以传
0;非连续内存请传真实行跨度。 - 对连续图像,最小 stride 是
width * channels * sizeof(T)。 - 部分算子会分配内部临时工作区;如果分配失败会返回
ACL_ERR_NOMEM。
下一步: 查看 API 参考 或 算子 tier 列表。