4. 服务发现与提供

任务说明

本案例实现基于AUTOSAR Adaptive Platform(AP)中ara::com通信中间件的方法调用(Method Call)机制。目标是通过ara::com的服务代理(Proxy)与服务提供(Skeleton)接口,完成客户端到服务端的远程方法调用,并获取返回值。案例聚焦于C++实现、运行时行为与验证路径,不涉及ara::com完整规范的所有细节。

实现方案

采用ara::com标准API风格,定义服务接口(Service Interface),实现Skeleton端(服务提供者)与Proxy端(服务调用者)。方法调用采用请求-响应模式:Proxy调用方法后阻塞等待Skeleton处理并返回结果。为保持案例独立可运行,使用内存中的直接调用模拟通信传输层,不依赖真实网络或操作系统IPC。

代码实现

// service_interface.h
#pragma once
#include <cstdint>
#include <functional>
#include <memory>

namespace ara {
namespace com {

// 方法调用返回值封装
template <typename T>
class MethodResult {
public:
    explicit MethodResult(T val) : value_(val), valid_(true) {}
    MethodResult() : value_(), valid_(false) {}
    bool IsValid() const { return valid_; }
    T GetValue() const { return value_; }
private:
    T value_;
    bool valid_;
};

// 服务接口定义:算术运算服务
class ArithmeticService {
public:
    // 方法ID
    static constexpr uint32_t kMethodAdd = 1;
    static constexpr uint32_t kMethodMultiply = 2;

    // 方法签名
    using AddHandler = std::function<int32_t(int32_t, int32_t)>;
    using MultiplyHandler = std::function<int32_t(int32_t, int32_t)>;
};

} // namespace com
} // namespace ara
// skeleton.h
#pragma once
#include "service_interface.h"
#include <unordered_map>
#include <functional>

namespace ara {
namespace com {

// Skeleton:服务提供端
class ArithmeticSkeleton {
public:
    void SetAddHandler(ArithmeticService::AddHandler handler) {
        add_handler_ = std::move(handler);
    }
    void SetMultiplyHandler(ArithmeticService::MultiplyHandler handler) {
        multiply_handler_ = std::move(handler);
    }

    // 处理来自Proxy的调用(模拟通信层分发)
    MethodResult<int32_t> Dispatch(uint32_t method_id, int32_t a, int32_t b) {
        switch (method_id) {
            case ArithmeticService::kMethodAdd:
                if (add_handler_) return MethodResult<int32_t>(add_handler_(a, b));
                break;
            case ArithmeticService::kMethodMultiply:
                if (multiply_handler_) return MethodResult<int32_t>(multiply_handler_(a, b));
                break;
            default:
                break;
        }
        return MethodResult<int32_t>(); // 无效调用
    }

private:
    ArithmeticService::AddHandler add_handler_;
    ArithmeticService::MultiplyHandler multiply_handler_;
};

} // namespace com
} // namespace ara
// proxy.h
#pragma once
#include "service_interface.h"
#include "skeleton.h"

namespace ara {
namespace com {

// Proxy:服务调用端
class ArithmeticProxy {
public:
    // 构造时绑定到Skeleton(模拟服务发现与连接)
    explicit ArithmeticProxy(ArithmeticSkeleton& skeleton) : skeleton_(skeleton) {}

    // 同步方法调用:加法
    MethodResult<int32_t> Add(int32_t a, int32_t b) {
        return skeleton_.Dispatch(ArithmeticService::kMethodAdd, a, b);
    }

    // 同步方法调用:乘法
    MethodResult<int32_t> Multiply(int32_t a, int32_t b) {
        return skeleton_.Dispatch(ArithmeticService::kMethodMultiply, a, b);
    }

private:
    ArithmeticSkeleton& skeleton_;
};

} // namespace com
} // namespace ara
// main.cpp
#include "proxy.h"
#include <iostream>

int main() {
    using namespace ara::com;

    // 1. 创建Skeleton并注册处理方法
    ArithmeticSkeleton skeleton;
    skeleton.SetAddHandler([](int32_t a, int32_t b) {
        return a + b;
    });
    skeleton.SetMultiplyHandler([](int32_t a, int32_t b) {
        return a * b;
    });

    // 2. 创建Proxy并连接到Skeleton
    ArithmeticProxy proxy(skeleton);

    // 3. 调用方法
    auto sum = proxy.Add(15, 27);
    auto product = proxy.Multiply(6, 7);

    // 4. 输出结果
    if (sum.IsValid()) {
        std::cout << "Add(15, 27) = " << sum.GetValue() << std::endl;
    } else {
        std::cout << "Add call failed" << std::endl;
    }

    if (product.IsValid()) {
        std::cout << "Multiply(6, 7) = " << product.GetValue() << std::endl;
    } else {
        std::cout << "Multiply call failed" << std::endl;
    }

    return 0;
}

编译与运行

# 编译(C++11或更高版本)
g++ -std=c++11 -o method_call_demo main.cpp

# 运行
./method_call_demo

预期输出

Add(15, 27) = 42
Multiply(6, 7) = 42

验证方法

运行程序后,观察标准输出是否与上述预期一致。若输出正确,则证明:Proxy端通过ara::com风格接口成功调用了Skeleton端注册的方法,并正确获取了返回值。可修改main.cpp中的输入参数或Skeleton中的处理逻辑,重新编译运行,验证方法调用的参数传递与结果返回机制正常工作。

ara::com 方法调用时序 Proxy 客户端 Skeleton 服务端 注册处理方法 Add(15, 27) 返回 42 Multiply(6, 7) 返回 42 Dispatch 分发 按 method_id 路由 方法调用 返回值 服务注册