首页 > 其他分享 >如何正确读取RTI中enum

如何正确读取RTI中enum

时间:2024-08-30 10:15:37浏览次数:10  
标签:读取 RTI enum dynamic State raw state

如何正确读取 RTI 中的 enum

背景

假设录制的 RTI 数据保存.dat 文件中,使用 DB browser for SQLite 查看.dat 文件,其中包含了要读取的 topic 数据,这个 topic 对应的 IDL 中含义 enum 类型,假设其定义如下:

module Sample {
    enum State {
        UNKNOWN = -1,
        MANUAL = 1,
        STARTED = 2,
        READY = 3
    };

    struct Info {
        Header header;
        State state;
        string name;
        boolean valid;
    };
};

之后使用 RTI 的接口从.dat 中读取了数据,返回的数据类型为dds::core::xtypes::DynamicData dynamic_raw,然后从中读取需要的字段,将其储存起来。

对于其他类型的数据,例如string或者boolean,可以通过下面的方式读取:

inline void SampleReader::FillData(dds::core::xtypes::DynamicData dynamic_raw) {
  if (dynamic_raw.member_exists("name")) {
    idl_message_.name(dynamic_raw.value<std::string>("name"));
  }

  if (dynamic_raw.member_exists("valid")) {
    idl_message_.valid(dynamic_raw.value<bool>("valid"));
  }
}

但是对于enum类型的数据,直接通过value读取是不行的,

inline void SampleReader::FillData(dds::core::xtypes::DynamicData dynamic_raw) {
  if (dynamic_raw.member_exists("state")) {
    idl_message_.state(dynamic_raw.value<Sample::State>("state"));
  }
}

这样做会提示未定义符号,例如:

undefined symbol: _ZNK3rti4core6xtypes15DynamicDataImpl5valueIN3dds4core9safe_enumIN15Sample8State_defENS9_4typeEEEEET_RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

这个原因比较奇怪,实际上这个类型Sample::State被导出了,idl_message_就是Sample::State类型的,可在读取的时候就不能这么使用。考虑到 enum 可能是一个 int 类型,所以可以通过下面的方式读取:

auto state{dynamic_raw.value<int32_t>("state")};
idl_message_.state(static_cast<Sample::State>(state));

这样也不行,编译都过不了,报错为:

error: invalid conversion from ‘int’ to ‘dds::core::safe_enum<Sample::State_def>::inner_enum’ {aka ‘Sample::State_def::type’} [-fpermissive]

也就是不能将int类型直接转换为Sample::State类型。那么应该如何正确读取 DDS 中的 enum 呢?

解决方案

查看源代码,发现枚举Sample::State的定义为

struct State_def {
    enum type {
        UNKNOWN = -1,
        MANUAL = 1,
        STARTED = 2,
        READY = 3
    };
    static type get_default(){ return UNKNOWN;}
};

typedef ::dds::core::safe_enum< State_def > State;
NDDSUSERDllExport std::ostream& operator << (std::ostream& o,const State& sample);

Sample::State实际是dds::core::safe_enum的实例化,而safe_enum是一个模版类,其定义如下:

template<typename def, typename inner = typename def::type>
class UserDllExport safe_enum : public def {
public:

    /**
     * The underlying \p enum type
     *
     * To convert from an integer, \p static_cast it to the member type \p inner_enum:
     *
     * \code
     * int reliability_as_int = 2;
     * ReliabilityKind reliability = static_cast<ReliabilityKind::inner_enum>(reliability_as_int);
     * \endcode
     */
    typedef inner inner_enum;

public:

    /**
     * @brief Initializes the enumeration to zero
     *
     * @note Zero may not be a valid enumerator. It's best to assign a valid
     * enumerator whenever possible:
     * \code
     * Reliability reliability = Reliability::RELIABLE;
     * \endcode
     */
    safe_enum() : val(static_cast<inner>(0))
    {
    }

    /**
     * @brief Copy constructor
     */
    safe_enum(inner_enum v) : val(v) {}

    /**
     * @brief Retrieves the actual \p enum value
     */
    inner_enum underlying() const { return val; }


private:
    inner_enum val;
};

inner_enum的注释中提到,可以通过static_castint转换为inner_enum,所以可以通过下面的方式读取:

inline void SampleReader::FillData(dds::core::xtypes::DynamicData dynamic_raw) {
  if (dynamic_raw.member_exists("state")) {
    auto state{dynamic_raw.value<int32_t>("state")};
    idl_message_.state(static_cast<Sample::State::inner_enum>(state));
  }
}

原来解决方案就在源代码里面……

标签:读取,RTI,enum,dynamic,State,raw,state
From: https://www.cnblogs.com/tianshihao/p/18388002

相关文章

  • java中的enum-java中特殊的class;通过字节码来分析enum构成
    §1 先思考一个问题先思考一个问题:我们在enum类里,可以直接使用 values() 或 valueOf(Stringname) 方法,我们也没有在enum类里定义这两个方法,怎么就能直接使用呢? 这里先按下不表。下面是正文。§2enum类及其编译后的字节码在java编程中,我们经常会定义和使用枚举。简......
  • python基础(11文件读取)
    python系列文章目录python基础(01变量&数据类型&运算符)python基础(02序列共性)python基础(03列表和元组)python基础(04字符串&字典)python基础(05集合set)python基础(06控制语句)python基础(07函数)python基础(08类和对象)python基础(09闭包&装饰器)python基础(10异常处理)文章......
  • python读取配置文件&&简单封装 公共配置文件 config
    之前有做过把爬虫数据写到数据库中的练习,这次想把数据库信息抽离到一个ini配置文件中,这样做的好处在于可以在配置文件中添加多个数据库,方便切换(另外配置文件也可以添加诸如邮箱、url等信息)1.configparser模块python使用自带的configparser模块用来读取配置文件,配置文......
  • Python模块之functools.partial
    在Python编程中,functools.partial是一个强大的工具,它提供了一种部分应用函数的方式,能够在创建新函数时固定部分参数,从而在后续调用中减少需要传递的参数数量。本文将深入介绍functools.partial的基本概念、使用方法,并通过丰富的示例代码演示其在不同场景中的实际应用。什么是func......
  • 【Markdown笔记】设置字体颜色——转载https://blog.csdn.net/u012028275/article/det
     【Markdown笔记】设置字体颜色dadalaohua于2021-04-0517:53:19发布阅读量5.7w 收藏 293点赞数103分类专栏: Markdown笔记 文章标签: markdown latex html版权GitCode开源社区文章已被社区收录加入社区Markdown笔记专......
  • ArgoWorkflow教程(三)---使用 Artifacts 实现步骤间文件共享
    上一篇我们分析了Workflow、WorkflowTemplate、template之间的关系。本篇主要分析如何在argo-workflow中使用S3存储artifact实现步骤之间的文件共享。本文主要解决两个问题:1)artifact-repository如何配置2)Workflow中如何使用1.artifact-repository配置ArgoWork......
  • NRRD文件的读取及保存
    importnrrdimportnumpyasnp#读取.nrrd文件defread_and_save_nrrd(filename,save_path):#读取文件data,header=nrrd.read(filename)#打印数据和选项信息print("Data:",data)print("Options:",header)#保存数据到新......
  • IEnumrable接口 GetEnumerator方法 foreach 遍历 自定义 迭代器
    **能用foreach遍历访问的对象需要实现什么接口或声明什么方法**要使用foreach循环,对象必须实现IEnumerable接口或者声明GetEnumerator方法。解释IEnumerable接口:这个接口定义了一个名为GetEnumerator的方法,该方法返回一个枚举器,允许客户端代码逐个访问集合......
  • BeanUtils.copyProperties方法
    BeanUtils.copyProperties方法通常是通过反射(Reflection)实现的。这个方法是ApacheCommonsBeanUtils库中的一个核心功能,它允许开发者在运行时动态地访问和操作对象的属性和方法。通过使用反射,BeanUtils.copyProperties能够检查对象的类定义,找出可用的getter和setter......
  • kafka如何合理设置broker、partition、consumer数量
    目录1.broker的数量最好大于等于partition数量2.consumer数量最好和partition数量一致3.总结1.broker的数量最好大于等于partition数量一个partition最好对应一个硬盘,这样能最大限度发挥顺序写的优势。一个broker如果对应多个partition,需要随机分发,顺序IO会退化成随机IO。实......