You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于C++多态设计Vulkan API JSON多命令列表解析器

Vulkan命令解析器的面向对象设计方案

核心设计思路

用工厂模式+多态解决大量Vulkan命令的解析问题:定义抽象基类统一所有命令的接口,每个具体Vulkan命令对应一个派生类负责自身JSON解析逻辑;工厂类通过command_name字段映射创建对应派生类实例,彻底规避大量if/else分支。

1. 定义抽象命令基类

基类提供统一的解析、输出接口,存储所有命令的通用字段:

#include <nlohmann/json.hpp>
#include <string>

using json = nlohmann::json;

class VulkanCommand {
public:
    virtual ~VulkanCommand() = default;
    // 纯虚函数,由派生类实现具体解析逻辑
    virtual void parse(const json& cmd_json) = 0;
    // 统一的命令信息输出接口
    virtual void print() const = 0;

    const std::string& getCommandName() const { return command_name_; }

protected:
    std::string command_name_;
    uint32_t call_index_;
    uint32_t thread_id_;
    std::string return_value_;
};

2. 实现具体命令派生类

每个Vulkan命令对应一个派生类,专注解析自身特有参数结构:

示例:VkGetDeviceQueueCommand

class VkGetDeviceQueueCommand : public VulkanCommand {
public:
    VkGetDeviceQueueCommand() { command_name_ = "vkGetDeviceQueue"; }

    void parse(const json& cmd_json) override {
        // 解析通用字段
        call_index_ = cmd_json["call_index"];
        thread_id_ = cmd_json["threadId"];
        return_value_ = cmd_json["return_value"];

        // 解析特有参数
        const auto& params = cmd_json["parameters"];
        device_ = params["device"];
        queue_family_index_ = params["queueFamilyIndex"];
        queue_index_ = params["queueIndex"];
        p_queue_ = params["pQueue"];
    }

    void print() const override {
        std::cout << "Command: " << command_name_ << "\n"
                  << "Call Index: " << call_index_ << "\n"
                  << "Thread ID: " << thread_id_ << "\n"
                  << "Return Value: " << return_value_ << "\n"
                  << "Parameters:\n"
                  << "  Device: " << device_ << "\n"
                  << "  Queue Family Index: " << queue_family_index_ << "\n"
                  << "  Queue Index: " << queue_index_ << "\n"
                  << "  pQueue: " << p_queue_ << "\n\n";
    }

private:
    std::string device_;
    uint32_t queue_family_index_;
    uint32_t queue_index_;
    std::string p_queue_;
};

示例:VkCreateFenceCommand

// 嵌套参数对应的辅助结构体
struct FenceCreateInfo {
    std::string s_type;
    std::string flags;
    std::string p_next;
};

class VkCreateFenceCommand : public VulkanCommand {
public:
    VkCreateFenceCommand() { command_name_ = "vkCreateFence"; }

    void parse(const json& cmd_json) override {
        // 解析通用字段
        call_index_ = cmd_json["call_index"];
        thread_id_ = cmd_json["threadId"];
        return_value_ = cmd_json["return_value"];

        // 解析特有参数
        const auto& params = cmd_json["parameters"];
        device_ = params["device"];
        
        // 解析嵌套的pCreateInfo
        const auto& create_info_json = params["pCreateInfo"];
        create_info_.s_type = create_info_json["sType"];
        create_info_.flags = create_info_json["flags"];
        create_info_.p_next = create_info_json["pNext"];

        p_allocator_ = params["pAllocator"];
        p_fence_ = params["pFence"];
    }

    void print() const override {
        std::cout << "Command: " << command_name_ << "\n"
                  << "Call Index: " << call_index_ << "\n"
                  << "Thread ID: " << thread_id_ << "\n"
                  << "Return Value: " << return_value_ << "\n"
                  << "Parameters:\n"
                  << "  Device: " << device_ << "\n"
                  << "  Fence Create Info:\n"
                  << "    sType: " << create_info_.s_type << "\n"
                  << "    flags: " << create_info_.flags << "\n"
                  << "    pNext: " << create_info_.p_next << "\n"
                  << "  pAllocator: " << p_allocator_ << "\n"
                  << "  pFence: " << p_fence_ << "\n\n";
    }

private:
    std::string device_;
    FenceCreateInfo create_info_;
    std::string p_allocator_;
    std::string p_fence_;
};

3. 实现命令工厂类

工厂类通过哈希表存储命令名称到实例创建函数的映射,新增命令只需注册,无需修改工厂逻辑:

#include <unordered_map>
#include <functional>
#include <memory>

class VulkanCommandFactory {
public:
    // 单例模式,保证全局唯一工厂实例
    static VulkanCommandFactory& getInstance() {
        static VulkanCommandFactory instance;
        return instance;
    }

    // 注册命令:绑定命令名称与实例创建函数
    void registerCommand(const std::string& cmd_name, std::function<std::unique_ptr<VulkanCommand>()> creator) {
        creators_[cmd_name] = std::move(creator);
    }

    // 根据JSON创建对应命令实例并完成解析
    std::unique_ptr<VulkanCommand> createCommand(const json& cmd_json) {
        std::string cmd_name = cmd_json["command_name"];
        auto it = creators_.find(cmd_name);
        if (it != creators_.end()) {
            auto cmd = it->second();
            cmd->parse(cmd_json);
            return cmd;
        }
        // 处理未知命令,返回空指针
        return nullptr;
    }

private:
    VulkanCommandFactory() = default;
    ~VulkanCommandFactory() = default;
    VulkanCommandFactory(const VulkanCommandFactory&) = delete;
    VulkanCommandFactory& operator=(const VulkanCommandFactory&) = delete;

    std::unordered_map<std::string, std::function<std::unique_ptr<VulkanCommand>()>> creators_;
};

4. 注册命令并运行解析逻辑

初始化时注册所有支持的命令,然后逐行读取并解析JSON文件:

#include <iostream>
#include <fstream>
#include <string>

// 简化注册逻辑的宏
#define REGISTER_VK_COMMAND(cmd_class) \
    VulkanCommandFactory::getInstance().registerCommand(#cmd_class, []() { return std::make_unique<cmd_class>(); })

int main() {
    // 注册所有支持的Vulkan命令
    REGISTER_VK_COMMAND(VkGetDeviceQueueCommand);
    REGISTER_VK_COMMAND(VkCreateFenceCommand);

    // 读取多行JSON文件
    std::ifstream file("vulkan_commands.json");
    if (!file.is_open()) {
        std::cerr << "Failed to open command file\n";
        return 1;
    }

    std::string line;
    while (std::getline(file, line)) {
        if (line.empty()) continue;
        try {
            json cmd_json = json::parse(line);
            auto cmd = VulkanCommandFactory::getInstance().createCommand(cmd_json);
            if (cmd) {
                cmd->print();
            } else {
                std::cout << "Unknown command: " << cmd_json["command_name"] << "\n";
            }
        } catch (const json::parse_error& e) {
            std::cerr << "Parse error: " << e.what() << "\n";
        }
    }

    return 0;
}

扩展说明

  • 新增命令:只需创建对应派生类,调用REGISTER_VK_COMMAND宏注册即可,完全符合开放封闭原则。
  • 嵌套参数:可通过定义辅助结构体/类处理,保持解析逻辑的清晰性。
  • 错误处理:可在基类或工厂中添加参数校验、异常捕获逻辑,提升鲁棒性。

内容的提问来源于stack exchange,提问作者Andre Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 07:28:23