Apache Celix 快速入门与集成示例

Apache Celix 快速入门与集成示例,从零编写最小 C bundle、编译打包、加载运行,进阶演示依赖管理器组件与服务注册,并对比 C/C++ OSGi 框架选型。

Apache CelixApache Celix2026/10/14

Apache Celix 快速入门与集成示例

目标:从零演示 Apache Celix 3.0 的典型使用路径——编写最小 C bundle、编译打包、加载运行,再到基于依赖管理器(Dependency Manager)的组件与服务集成示例。所有命令与回显已在 Ubuntu 22.04.5 LTS 与 CentOS 8 双环境实测通过。

一、环境信息

项目实测值
操作系统Ubuntu 22.04.5 LTS / CentOS 8
Apache Celix3.0.0(源码构建安装于 /opt/celix)
编译器gcc 11.4(Ubuntu)/ gcc 8.5(CentOS)
示例工程目录/opt/my-bundle
bundle 产物/opt/my-bundle/build/my_bundle.zip

二、前置条件

2.1 前置说明

本指南假设已完成 Celix 安装(见《Ubuntu 22.04 安装 Apache Celix 指南》或《CentOS 8 安装 Apache Celix 指南》),系统具备 gcc/cmake 与 Celix 开发头文件。

2.2 前置验证

ls /opt/celix/bin/celix
ls /opt/celix/include/celix/celix_bundle_activator.h
cmake --version | head -1

实测回显(Ubuntu 22.04):

/opt/celix/bin/celix
/opt/celix/include/celix/celix_bundle_activator.h
cmake version 3.22.1

三、核心概念速览

3.1 概念说明

使用 Celix 前先建立三个核心概念:OSGi 运行时框架(Framework)、bundle、activator。框架负责管理 bundle 的生命周期与服务注册;bundle 是模块化单元(Celix 中是一个 zip 包,内含共享库与 MANIFEST.json 描述);activator 是 bundle 的入口,框架在启动/停止 bundle 时调用其回调。

💡 技术拓展:C/C++ 生态中实现「运行时模块化 + 服务注册」的主流方案对比——

方案语言模块单元服务机制适用场景
Apache CelixC/C++bundle(zip 内共享库)原生 OSGi 服务注册/依赖管理器嵌入式、IoT、长驻服务
原生 OSGi(Equinox/Felix)JavaJAR(OSGi 规范)OSGi ServiceRegistryJava 服务模块化
自研插件框架(dlopen/dlsym)C/C++.so手写函数指针表简单插件、快速实现
消息中间件解耦任意进程/消息消息队列分布式、跨语言

本指南采用 Apache Celix:其把 OSGi 的「生命周期 + 服务动态注册」能力以 C API 提供,bundle 直接编译为共享库,无需 JVM,适合对资源占用敏感的 C/C++ 服务端。

3.2 本指南路线

按「最小 bundle → 加载运行 → 服务注册 → 依赖管理器组件」递进,每步给出可独立执行的工程与回显。

四、最小 bundle:编写、编译与加载

4.1 编写源码

创建工程目录:

mkdir -p /opt/my-bundle/src

编写 /opt/my-bundle/src/bundle.c(activator 实现 bundle 生命周期回调):

#include <stdio.h>
#include <celix_bundle_activator.h>

typedef struct activator_data {
    /*empty*/
} activator_data_t;

static celix_status_t activator_start(activator_data_t *data, celix_bundle_context_t *ctx) {
    printf("[my-bundle] activator_start: hello from my-bundle, bundle id=%li\n",
           celix_bundleContext_getBundleId(ctx));
    return CELIX_SUCCESS;
}

static celix_status_t activator_stop(activator_data_t *data, celix_bundle_context_t *ctx) {
    printf("[my-bundle] activator_stop: goodbye from my-bundle, bundle id=%li\n",
           celix_bundleContext_getBundleId(ctx));
    return CELIX_SUCCESS;
}

CELIX_GEN_BUNDLE_ACTIVATOR(activator_data_t, activator_start, activator_stop)

代码说明:

  • celix_bundle_activator.h 提供 activator 相关宏与类型;
  • activator_start/activator_stop 分别是 bundle 启动/停止回调,返回值 CELIX_SUCCESS 表示成功;
  • CELIX_GEN_BUNDLE_ACTIVATOR 宏把上述回调与数据结构关联,生成框架要求的导出符号;
  • celix_bundleContext_getBundleId(ctx) 取当前 bundle 的 id。

编写 /opt/my-bundle/CMakeLists.txt(bundle 打包描述):

cmake_minimum_required(VERSION 3.19)
project(my_bundle C)

find_package(Celix REQUIRED)

add_celix_bundle(my_bundle
    VERSION 1.0.0
    SOURCES src/bundle.c
)

说明:find_package(Celix) 加载 Celix 安装的 CMake 支持(-DCMAKE_PREFIX_PATH 指定安装前缀);add_celix_bundle 完成「编译共享库 + 生成 MANIFEST.json + 打包 zip」三步。

4.2 编译打包

cd /opt/my-bundle
cmake -S . -B build -DCMAKE_PREFIX_PATH=/opt/celix
cmake --build build

实测回显(Ubuntu 22.04,输出节选,实测首尾):

-- Configuring done
-- Generating done
-- Build files have been written to: /opt/my-bundle/build
[ 25%] Building C object CMakeFiles/my_bundle.dir/src/bundle.c.o
[ 50%] Linking C shared library libmy_bundle.so
[100%] Packaging my_bundle
[100%] Built target my_bundle_bundle
[100%] Built target celix-bundles

验证 bundle 包内容与描述:

unzip -l /opt/my-bundle/build/my_bundle.zip
unzip -p /opt/my-bundle/build/my_bundle.zip META-INF/MANIFEST.json

实测回显:

Archive:  /opt/my-bundle/build/my_bundle.zip
  Length      Date    Time    Name
---------  ---------- ----    ----
        0  2026-10-13 18:04   META-INF/
      329  2026-10-13 18:04   META-INF/MANIFEST.json
    16208  2026-10-13 18:04   libmy_bundle.so.1
---------  -------
{
    "CELIX_BUNDLE_SYMBOLIC_NAME" : "my_bundle",
    "CELIX_BUNDLE_VERSION" : "version<1.0.0>",
    "CELIX_BUNDLE_NAME" : "my_bundle",
    "CELIX_BUNDLE_ACTIVATOR_LIBRARY": "libmy_bundle.so.1",
    "CELIX_BUNDLE_PRIVATE_LIBRARIES" : ["libmy_bundle.so.1"],
    "CELIX_BUNDLE_MANIFEST_VERSION" : "version<2.0.0>"
}

4.3 加载运行

编写 JSON 运行配置,通过 CELIX_AUTO_START_0 指定自动加载的 bundle:

cat > /opt/my-bundle/config.json <<'EOF'
{
  "CELIX_AUTO_START_0": "file:///opt/my-bundle/build/my_bundle.zip"
}
EOF
cd /opt/my-bundle
timeout 8 /opt/celix/bin/celix config.json

实测回显:

[my-bundle] activator_start: hello from my-bundle, bundle id=1
[2026-10-13T18:05:15] [   info] [celix_framework] [framework_start:496] Celix framework started
[2026-10-13T18:05:23] [   info] [celix_framework] Stopping Celix framework due to signal Terminated
[my-bundle] activator_stop: goodbye from my-bundle, bundle id=1

验证结论:框架启动时执行 activator_start(bundle id=1),框架停止时执行 activator_stop,最小 bundle 全链路可用。

五、集成示例:服务注册与依赖管理器

5.1 示例说明

真实集成中 bundle 之间通过「服务注册/引用」协作。本节基于 Celix 官方示例结构(hello_world_c 同构)扩展:示例 bundle 在 activator_start 中注册一个自定义服务,在 activator_stop 中注销,并演示用依赖管理器组件(dm)管理组件生命周期。

5.2 服务注册示例(calc 服务)

创建 /opt/my-bundle-svc/src/bundle.c:

#include <stdio.h>
#include <celix_bundle_activator.h>

typedef struct calc_service {
    int (*add)(int a, int b);
} calc_service_t;

static int calc_add(int a, int b) {
    return a + b;
}

typedef struct activator_data {
    long svc_id;
} activator_data_t;

static celix_status_t activator_start(activator_data_t *data, celix_bundle_context_t *ctx) {
    calc_service_t svc = { .add = calc_add };
    long svcId = celix_bundleContext_registerService(ctx, &svc, "calc_service", NULL);
    if (svcId < 0) {
        return CELIX_SERVICE_EXCEPTION;
    }
    data->svc_id = svcId;
    printf("[svc-bundle] calc_service registered, svc_id=%li\n", svcId);
    return CELIX_SUCCESS;
}

static celix_status_t activator_stop(activator_data_t *data, celix_bundle_context_t *ctx) {
    celix_bundleContext_unregisterService(ctx, data->svc_id);
    printf("[svc-bundle] calc_service unregistered, svc_id=%li\n", data->svc_id);
    return CELIX_SUCCESS;
}

CELIX_GEN_BUNDLE_ACTIVATOR(activator_data_t, activator_start, activator_stop)

代码说明:

  • celix_bundleContext_registerService(ctx, &svc, "calc_service", NULL) 注册服务,返回服务 ID(long),小于 0 表示失败;
  • celix_bundleContext_unregisterService(ctx, svc_id) 在停止回调中显式注销服务,否则框架会告警「Dangling service registration」并触发断言(见常见问题 Q3)。

创建 /opt/my-bundle-svc/CMakeLists.txt:

cmake_minimum_required(VERSION 3.19)
project(my_bundle_svc C)

find_package(Celix REQUIRED)

add_celix_bundle(my_bundle_svc
    VERSION 1.0.0
    SOURCES src/bundle.c
)

编译:

cd /opt/my-bundle-svc
cmake -S . -B build -DCMAKE_PREFIX_PATH=/opt/celix
cmake --build build

实测回显(输出节选,实测首尾):

[ 25%] Building C object CMakeFiles/my_bundle_svc.dir/src/bundle.c.o
[ 50%] Linking C shared library libmy_bundle_svc.so
[100%] Packaging my_bundle_svc
[100%] Built target my_bundle_svc_bundle

5.3 加载服务 bundle 实测

cat > /opt/my-bundle-svc/config.json <<'EOF'
{
  "CELIX_AUTO_START_0": "file:///opt/my-bundle-svc/build/my_bundle_svc.zip"
}
EOF
cd /opt/my-bundle-svc
timeout 8 /opt/celix/bin/celix config.json

实测回显:

[svc-bundle] calc_service registered, svc_id=2
[2026-10-13T18:34:06] [   info] [celix_framework] [framework_start:496] Celix framework started
[2026-10-13T18:34:14] [   info] [celix_framework] Stopping Celix framework due to signal Terminated
[svc-bundle] calc_service unregistered, svc_id=2

验证结论:bundle 启动时服务注册成功(svc_id=2),框架停止时服务被显式注销,全程无告警,服务注册/注销生命周期闭环正常。

5.4 依赖管理器(Dependency Manager)集成

依赖管理器是 Celix 官方推荐的组件管理方式:把「组件(component)+ 依赖(dependency)」用声明式 API 组装,框架自动处理服务注入。其典型结构(官方 dm_example 同构):

/* 组件实现 */
static void component_init(void *handle) { /* 组件初始化 */ }
static void component_start(void *handle) { /* 依赖就绪后启动 */ }
static void component_stop(void *handle)  { /* 依赖解除时停止 */ }

/* activator 中组装 */
celix_dependency_manager_t *dm = celix_bundleContext_getDependencyManager(ctx);
celix_dm_component_t *cmp = celix_dmComponent_create(dm, "my_component");
celix_dmComponent_setImplement(cmp, handle, component_init, component_start, component_stop);
celix_dmComponent_addRequiredService(cmp, "calc_service", NULL, NULL);
celix_dmComponent_start(cmp);

要点说明:组件依赖 calc_service,框架只在 calc_service 可用时调用 component_start,服务消失时调用 component_stop,实现动态装配;相比手工 registerService/useService,dm 自动处理服务跟踪。

5.5 常用 shell 运维集成

运行时通过 shell 命令查看 bundle 与服务状态(详见《Apache Celix 常用 CLI 命令与工具详解》):

-> lb
-> query -v
-> quit

lb 列出已加载 bundle,query -v 列出服务及其属性,quit 优雅退出框架。

六、注意事项

  1. bundle 加载顺序用启动级别控制(CELIX_AUTO_START_0 到 6),被依赖的 bundle 放小级别号;
  2. 运行配置必须为 JSON 格式,字符串值加引号;
  3. 修改 bundle 源码后需重新 cmake --build build,且建议删除 bundle 缓存(或配置 org.osgi.framework.storage.clean=onFirstInit)避免加载旧包;
  4. activator 回调必须返回 CELIX_SUCCESS,失败会导致 bundle 进入错误状态;
  5. Celix 3.x 为开发版,C API 可能随版本调整,生产锁定版本号。

七、常见问题(FAQ)

Q1:编译报找不到 Celix 包(find_package 失败)?

实测报错形态:

CMake Error: Could not find a package configuration file provided by "Celix"

解决:cmake 配置时指定安装前缀:cmake -S . -B build -DCMAKE_PREFIX_PATH=/opt/celix。

Q2:启动后 activator 未打印输出?

检查:配置文件是否为 JSON 且 bundle 路径正确;确认 CELIX_AUTO_START_x 的 x 级别未被更高优先级占用;确认 bundle zip 内 MANIFEST.json 的 CELIX_BUNDLE_ACTIVATOR_LIBRARY 与 .so 文件名一致。

Q3:框架停止时报「Dangling service registration」并触发断言崩溃?

实测报错:

[  error] [celix_framework] [bundleContext_cleanupServiceRegistration:843] Dangling service registration with svcId 2, for bundle my_bundle_svc. Add missing 'celix_bundleContext_unregisterService' calls.
celix: .../bundle_context.c:97: bundleContext_destroy: Assertion `celix_arrayList_size(context->svcRegistrations) == 0' failed.

原因:bundle 注册了服务但在停止回调中没有显式注销。解决:在 activator_stop 中调用 celix_bundleContext_unregisterService(ctx, svc_id)(见 5.2 完整代码)。

Q4:bundle 修改后运行还是旧行为?

删除框架 bundle 缓存目录后重跑:

rm -rf .cache /opt/celix/bundle-cache

Q5:多个 bundle 如何共享头文件与库?

头文件由 Celix 安装目录提供(/opt/celix/include/celix);业务公共头文件可放入独立目录,各 bundle CMakeLists 中 include_directories 引用;公共逻辑建议单独编译为共享库并用 CELIX_BUNDLE_PRIVATE_LIBRARIES 或普通链接引入。

八、参考链接

  1. Celix 示例代码:https://github.com/apache/celix/tree/master/examples/celix-examples
  2. Celix bundle 打包宏文档:https://github.com/apache/celix/blob/master/cmake/cmake_celix/BundlePackaging.cmake
  3. Celix 依赖管理器文档:https://github.com/apache/celix/tree/master/libs/framework
  4. C 语言 bundle activator 头文件:https://github.com/apache/celix/blob/master/libs/framework/include/celix/celix_bundle_activator.h
  5. OSGi 规范:https://www.osgi.org/