Как связать данные из одной структуры в другую - PullRequest
0 голосов
/ 16 января 2020

Я делаю некоторые изменения в репозитории Ar tNet. Я хочу немного расширить его, но чтобы сделать это эффективно, у меня возникла пара вопросов, на которые я не знаю ответа. Пожалуйста, рассмотрите фрагмент кода ниже. Как видите, у меня есть три структуры:

  • ArtNetNode : здесь содержится вся информация об идентификации узла. IP и короткое / длинное имя могут меняться в ходе программы.
  • ArtPollReplyPack : к этой структуре прикреплен упакованный аргумент. Я использую эту структуру позже, поэтому отправляю пакет udp. Это действительно весь пакет, как указано в спецификациях протокола ar tnet.
  • ArtDmxPack : аналогично пункту два, но есть возможность доказать, что данные из структуры узла используется в нескольких пакетах.

Текущая реализация хранит много копий информации c, я имею в виду IP-адрес, ма c, короткое и длинное имя. Если один из этих параметров изменяется, мне нужно изменить его во всех трех местах. Что не очень эффективно. Мой вопрос заключается в том, как я могу сделать это эффективным, поэтому мне нужно только изменить node.ip вместо всех трех местоположений. Поиски привели меня к указателям, которые действительно имеют смысл. Тем не менее, это может испортить структуру упаковки, поскольку ArtPollReplyPack и ArtDmxPack действительно являются полным набором данных пакета. Может ли кто-нибудь помочь мне преодолеть это? Может быть, примером.

Спасибо за ваше время!

К вашему сведению: я использую Teensyduino на плате Teensy 3.2 с Wiz8xx Ethe rnet портом.

#include <Ethernet.h>
#include <EthernetUdp.h>

EthernetUDP Udp;

byte mac[] = {0x04, 0xE9, 0xE5, 0x00, 0x69, 0xEC};
IPAddress controllerIP(192, 168, 0, 2);

struct ArtNetNode {
  IPAddress  ip;
  uint8_t  mac[6];
  uint8_t  oemH;            
  uint8_t  oemL;
  uint8_t  shortname[18];
  uint8_t  longname[64];
};

struct ArtPollReplyPack {
  uint8_t  id[8];
  uint16_t opCode;          
  uint8_t  ip[4];
  uint8_t  mac[6];           
  uint16_t port;
  uint8_t  oemH;          
  uint8_t  oemL;
  uint8_t  shortname[18];   
  uint8_t  longname[64];
}__attribute__((packed));

struct ArtDmxPack {
  uint8_t  id[8];
  uint16_t opCode;          
  uint8_t  ip[4];           
  uint16_t port;
  uint8_t  DmxData[512];                 
}__attribute__((packed));

struct ArtNetNode node;
struct ArtPollReplyPack ArtPollReply;
struct ArtDmxPack ArtDmx;

void setup() {
  ArtPollReply.oemH = node.oemH;
  ArtPollReply.oemL = node.oemL;

  memcpy(ArtPollReply.shortname, node.shortname, sizeof(node.shortname));
  memcpy(ArtPollReply.longname, node.longname, sizeof(node.longname));
  memcpy(node.mac, mac, sizeof(mac));
  memcpy(ArtPollReply.mac, node.mac, sizeof(node.mac));

  Ethernet.begin(mac);
  Udp.begin(6454);
}

void loop() {
  switch(Ethernet.maintain()) {
    case 1:
    case 3:
      // rebind / renew failed.
      break;

    case 2:
    case 4:
      // update the node IP address.
      memcpy(node.ip, Ethernet.localIP(), 4);
    case 0:
    default: 
      break;
  }

  Udp.beginPacket(controllerIP, 6454);
  Udp.write((uint8_t *)&ArtPollReply, sizeof(ArtPollReply));
  Udp.endPacket();
}

Ответы [ 2 ]

0 голосов
/ 26 января 2020

Невозможно изменить данные двух или более структур одновременно. Но вы можете прикрепить их к одной указанной c структуре, чтобы при изменении данных этой указанной c структуры или, скажем, базовой структуры это влияло на все остальные структуры. В общем, просто позвоните Базовая структура во всех других структурах. Например, обратитесь к приведенному ниже коду:

struct o{
    int data=3;
    char name='c';
}one;
struct t{
    int data=one.data;
    char name=one.name;
}two;

Теперь, когда вы вызываете структуру два, он будет печатать данные из структуры один.

0 голосов
/ 23 января 2020

Нет реального способа установить все три IP-адреса на одно и то же значение без установки всех трех IP-адресов на одно и то же значение.

Однако вам не нужно использовать вызовы функции memcpy () ... если вы хотите быть очень грязным, вы можете воспользоваться тем, что IP-адреса имеют длину 4 байта, то есть uint32_t, поэтому если вы приведете к этому, вы можете назначить напрямую вместо использования memcpy, то есть

union IP {
    uint8_t  ip[4];
    uint32_t ipAsInt;
};

, теперь просто скопируйте ipAsInt вместо memcpying.

[Если честно, я не могу гарантировать, что компилятор все равно не оптимизирую это для вас]

...