C ++ memcpy массив для структурирования на основе типа транзакции - PullRequest
0 голосов
/ 21 февраля 2012

Эта процедура от конечного автомата для доступа к GPS через последовательный порт. Я пытаюсь приступить к работе, но он не копирует пакет отчета в структуру отчета.

Пакет отчета создается процедурой ввода-вывода, и когда пакет завершается, он передается в функцию отчета об обновлении. M_report.report.data заполнен правильно, и я его выбросил. Однако я не могу определить, как создать общий оператор memcpy для копирования данных в правильную структуру.

Пакет отчета может иметь три формата, но выводится в более чем 15 различных структурах в зависимости от кода / субкода. Копируется только часть данных отчета или расширенной структуры.

union _report_packet {
    struct _raw {
        UINT8 data[MAX_DATA];
    } raw;
    struct _report {
        UINT8  code;
        UINT8  data[MAX_DATA-1];
    } report;
    struct _extended {
        UINT8  code;
        UINT8  subcode;
        UINT8  data[MAX_DATA-2];
    } extended;
} m_report;

struct _ecef_position_s {
    bool  valid;
    struct _0x42 {
        SINGLE x;               // X meters
        SINGLE y;               // Y meters
        SINGLE z;               // Z meters
        SINGLE time_of_fix;     // time of fix in GPS or UTC seconds 
    } report;
};

struct _ecef_position_d {
    bool  valid;
    struct _0x83 {
        DOUBLE x;               // X meters
        DOUBLE y;               // Y meters
        DOUBLE z;               // Z meters
        DOUBLE clock_bias;      // clock bias meters
        SINGLE time_of_fix;     // time of fix in GPS or UTC seconds 
    } report;
};


update_report() {

    void *src;
    void *dst;

    // save report
    switch (m_report.report.code) {

    case REPORT_ECEF_POSITION_S:
        m_ecef_position_s.valid = true;
        src = m_report.report.data;
        dst = &m_ecef_position_s.report;
        break;

    case REPORT_ECEF_POSITION_D:
        m_ecef_position_d.valid = true;
        src = m_report.report.data;
        dst = &m_ecef_position_d.report;
        break;

    .......more cases and some codes have sub-codes

    }

    memcpy(dst, src, std::min(m_report_length, rlen));
}

Я просмотрел несколько примеров, прочитал руководство и попытался собрать идеи из похожих вопросов, но все примеры, похоже, имеют дело с очень простым POD. Я просто не понимаю, как сделать прыжок в более сложную ситуацию. Можно ли это сделать даже в C ++?

обновление

rlen - это количество байтов в буфере m_report. В моем тестировании это правильная длина и всегда меньше максимальной длины 1024.

Нет ошибок: здесь дамп областей ввода и вывода:

m_report.raw.data []: 0 3 83 c8 6 8c 0 f 3 31 3a f 15 2 7 dc 2f a9 a7

отчет после переезда: f0 e 0 0 0 0 0 0 6d 79 43 4f 0 0 0 0 cb 86 e1

область вывода не изменяется.

То, что я предоставил, является упрощенным подмножеством кода. Я не знаю историю или как она возникла. Существует около 12 структур, которые в общей сложности содержат почти 300 строк, поэтому разработка способа перемещения m_report.data в соответствующую структуру позволит сэкономить много кода.

Я могу заполнить структуру, если объединю целочисленный массив без знака со структурой и получу цикл для его перемещения символ за символом. Это требует изменения всех структур и, возможно, нарушения существующего кода, который мне неизвестен.

Я надеюсь, что с memcpy есть способ перейти от массива к структуре, но я заблудился, указатели были определены как void * или const void *, а затем получили место назначения в различных форматах. Я также не уверен, почему указатель dst установлен со ссылкой, а src - нет. Ссылка на memcpy не дает достаточного фона для меня, чтобы понять, что требуется.

Таким образом, грубая сила выполнит работу, но я хотел бы понять более изящное (глазами смотрящего) решение.

Окончательное обновление

Никогда не заставлял memcpy работать в этой ситуации. Но узнал несколько вещей, которые должны были быть очевидными. Самое главное, я запускаю приложение в системе с прямым порядком байтов, а поток данных поступает из системы высокого уровня. Memcpy не будет правильно форматировать многобайтовые поля. Поэтому, если memcpy будет работать, он не даст правильных результатов.

Значит, грубая сила победит.

...