首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PythontoC++ (roscpp) struct.unpack

PythontoC++ (roscpp) struct.unpack
EN

Stack Overflow用户
提问于 2015-07-01 13:46:58
回答 2查看 529关注 0票数 1

我目前正在翻译一个罗间谍IMU驱动程序到roscpp,并且很难弄清楚这段代码做什么以及我如何翻译它。

代码语言:javascript
复制
def ReqConfiguration(self):
    """Ask for the current configuration of the MT device.
    Assume the device is in Config state."""
    try:
        masterID, period, skipfactor, _, _, _, date, time, num, deviceID,\
                length, mode, settings =\
                struct.unpack('!IHHHHI8s8s32x32xHIHHI8x', config)
    except struct.error:
        raise MTException("could not parse configuration.")
    conf = {'output-mode': mode,
            'output-settings': settings,
            'length': length,
            'period': period,
            'skipfactor': skipfactor,
            'Master device ID': masterID,
            'date': date,
            'time': time,
            'number of devices': num,
            'device ID': deviceID}
    return conf

我不得不承认,我以前从未与ros或python合作过。这不是从源代码1:1代码,我删除了行,我认为我知道他们做什么,但特别是尝试块是什么,我不明白。我真的很感激你的帮助,因为我有很长的时间。

如果有人好奇(上下文原因):我必须翻译的文件是mtdevice.py、mtnode.py和mtdef.py,可以在googleing中找到文件名+关键字ROS驱动程序。

提前谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-07-01 14:30:57

要对C++执行同样的操作,您需要使用各种参数声明一个struct

代码语言:javascript
复制
struct DeviceRecord {
    uint32_t masterId;
    uint16_t period, skipfactor, _a, _b;
    uint32_t _c;
    char date[8];
    char time[8];
    char padding[64];
    uint16_t num;
    uint32_t deviceID;
    uint16_t length, mode;
    uint32_t settings;
    char padding[8];
};

(这个结构可能已经在某个地方声明过了;它也可能使用"unsigned“而不是"uint32_t”,而不是"uint16_t",并且_a、_b、_c可能会有实名。)

一旦你有了你的结构,问题就是如何获得数据。这取决于数据在哪里。如果它在文件里,你会做这样的事情:

代码语言:javascript
复制
DeviceRecord rec; // An instance of the struct, whatever it's called
std::ifstream fin("yourfile.txt", std::ios::binary);
fin.read(reinterpret_cast<char*>(&rec), sizeof(rec));
// Now you can access rec.masterID etc

另一方面,如果它在内存中的某个地方(即,您有一个char*或void* ),那么您只需将其转换为:

代码语言:javascript
复制
void* data_source = get_data(...); // You'd get this from somewhere
DeviceRecord* rec_ptr = reinterpret_cast<DeviceRecord*>(stat_source);
// Now you can access rec_ptr->masterID etc

如果您有一个std::vector,您可以很容易地获得这样一个指针:

代码语言:javascript
复制
std::vector<uint8_t> data_source = get_data(...); // As above
DeviceRecord* rec_ptr = reinterpret_cast<DeviceRecord*>(data_source.data());
// Now you can access rec_ptr->masterID etc, provided data_source remains in scope. You should probably also avoid modifying data_source.

这里还有一个问题。您收到的数据是大端的,但是除非您有一个PowerPC或其他不寻常的处理器,否则您可能在一台小终端机器上。因此,在访问数据之前,您需要做一点字节交换。您可以使用以下函数来执行此操作。

代码语言:javascript
复制
template<typename Int>
Int swap_int(Int n) {
    if(sizeof(Int) == 2) {
        union {char c[2]; Int i;} swapper;
        swapper.i = n;
        std::swap(swapper.c[0], swapper.c[1]);
        n = swapper.i;
    } else if(sizeof(Int) == 4) {
        union {char c[4]; Int i;} swapper;
        swapper.i = n;
        std::swap(swapper.c[0], swapper.c[3]);
        std::swap(swapper.c[1], swapper.c[2]);
        n = swapper.i;
    }
    return n;
}

它们返回交换的值,而不是就地更改它,因此现在您可以使用类似于swap_int(rec->num)的内容访问数据。注意:上面的字节交换代码是未经测试的;稍后我将尝试编译它,并在必要时修复它。

如果没有更多的信息,我不能给你一个明确的方法,但也许这将足以帮助你自己解决它。

票数 1
EN

Stack Overflow用户

发布于 2015-07-01 13:51:25

这段代码解压缩了C结构的字段,即masterID、句点、跳过因子、_、日期、时间、num、deviceID、长度、模式、设置,将这些字段存储在Python字典中,并将字典作为调用结果返回。下划线是结构中没有使用的部分的占位符。

还请参见:https://docs.python.org/2/library/struct.html,例如,关于格式字符串('!IHHHHI8s8s32x32xHIHHI8x')的描述,它告诉解包函数结构是什么样的。

语法a,b,c,d=f ()意味着函数返回一个在Python中称为tuple的东西。通过将一个元组分配给多个变量,它被分割成它的字段。

示例:

代码语言:javascript
复制
 t = (1, 2, 3, 4)

 a, b, c, d = t

 # At this point a == 1, b == 2, c == 3, d == 4

用C++替换这段代码不应该太难,因为C++有与C非常相似的结构,所以requestConfiguration最简单的C++实现就是返回该结构。如果您希望更接近于Python功能,您的函数可以将结构的字段放入C++ STL映射中并返回该字段。格式字符串+链接指向的文档,告诉您结构中的数据类型和位置。

注意,它是unpack的第二个参数,它保存了数据,第一个参数只包含关于第二个参数的布局(格式)的信息,如链接中所解释的那样。第二个参数看起来好像是一个字符串,但实际上它是一个C结构。第一个参数告诉Python在哪里可以找到该结构中的内容。

因此,如果读取格式字符串上的文档,就可以找到第二个参数( strings )的布局。但也许你不需要。这取决于函数的调用方。它可能只是期望普通的C结构。

从您添加的评论中,我了解到您的函数中的代码比显示的要多。结构的字段被分配给类的属性。

如果您知道C struct (config)的字段名,那么可以将它们直接分配给C++类的属性。

代码语言:javascript
复制
// Pointer 'this' isn't needed but inserted for clarity

this->mode = config.mode;
this->settings = config.settings;
this->length = config.length;

我假设配置结构的字段名确实是模式、设置、长度等,但您必须验证这一点。这个结构的布局可能是在某些C头文件(或文档中)中声明的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31163199

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档