如何 link 从一个结构到另一个结构的数据
How to link data from one struct to the other
我正在对 ArtNet 存储库进行一些更改。我想稍微扩展一下,但为了有效地做到这一点,我有几个问题我不知道答案。
请考虑下面的代码。
如您所见,我有三个结构:
- ArtNetNode:包含所有节点标识信息。 IP 和 short/long 名称可以在程序期间更改。
- ArtPollReplyPack:此结构附加了压缩参数。我稍后使用这个结构,所以发送 udp 数据包。果然是artnet协议规范中规定的整包。
- ArtDmxPack: 与第二点类似,但可以证明来自节点结构的数据被用于多个数据包。
当前的实现保留了很多特定信息的副本,我指的是 IP 地址、mac、短名称和长名称。如果这些参数之一发生变化,我需要在所有三个位置上进行更改。这不是很有效。
我的问题是如何才能提高效率,所以我只需要更改 node.ip 而不是所有三个位置。搜索让我找到了真正有意义的指针。但是,我认为这会弄乱结构打包,因为 ArtPollReplyPack 和 ArtDmxPack 实际上是包的完整数据集。有什么可以帮助我克服这个问题吗?也许通过例子。
感谢您的宝贵时间!
仅供参考:我正在带有 Wiz8xx 以太网端口的 Teensy 3.2 板上使用 Teensyduino 实现。
#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();
}
如果不将所有三个 IP 地址设置为相同的值,就没有真正的方法可以将所有三个 IP 地址设置为相同的值。
但是,您不必使用 memcpy() 函数调用...如果您想要非常混乱,您可以利用 IP 地址是 4 个字节的事实,即 uint32_t, 所以如果你投射到你可以直接分配而不是使用 memcpy, 即
union IP {
uint8_t ip[4];
uint32_t ipAsInt;
};
现在只需复制 ipAsInt 而不是 memcpying。
[老实说,我不能保证编译器无论如何都不会为你优化]
无法同时更改两个或多个结构的数据。但是,您可以将它们附加到一个特定的结构,这样每当该特定结构的数据或我们可以说 Base Structure 发生变化时,它都会影响所有其他结构。总体而言,只需在所有其他结构中调用 Base Structure。
例如,参考下面的代码:
struct o{
int data=3;
char name='c';
}one;
struct t{
int data=one.data;
char name=one.name;
}two;
现在,当您调用结构二时,它将打印结构一的数据。
我正在对 ArtNet 存储库进行一些更改。我想稍微扩展一下,但为了有效地做到这一点,我有几个问题我不知道答案。 请考虑下面的代码。 如您所见,我有三个结构:
- ArtNetNode:包含所有节点标识信息。 IP 和 short/long 名称可以在程序期间更改。
- ArtPollReplyPack:此结构附加了压缩参数。我稍后使用这个结构,所以发送 udp 数据包。果然是artnet协议规范中规定的整包。
- ArtDmxPack: 与第二点类似,但可以证明来自节点结构的数据被用于多个数据包。
当前的实现保留了很多特定信息的副本,我指的是 IP 地址、mac、短名称和长名称。如果这些参数之一发生变化,我需要在所有三个位置上进行更改。这不是很有效。 我的问题是如何才能提高效率,所以我只需要更改 node.ip 而不是所有三个位置。搜索让我找到了真正有意义的指针。但是,我认为这会弄乱结构打包,因为 ArtPollReplyPack 和 ArtDmxPack 实际上是包的完整数据集。有什么可以帮助我克服这个问题吗?也许通过例子。
感谢您的宝贵时间!
仅供参考:我正在带有 Wiz8xx 以太网端口的 Teensy 3.2 板上使用 Teensyduino 实现。
#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();
}
如果不将所有三个 IP 地址设置为相同的值,就没有真正的方法可以将所有三个 IP 地址设置为相同的值。
但是,您不必使用 memcpy() 函数调用...如果您想要非常混乱,您可以利用 IP 地址是 4 个字节的事实,即 uint32_t, 所以如果你投射到你可以直接分配而不是使用 memcpy, 即
union IP {
uint8_t ip[4];
uint32_t ipAsInt;
};
现在只需复制 ipAsInt 而不是 memcpying。
[老实说,我不能保证编译器无论如何都不会为你优化]
无法同时更改两个或多个结构的数据。但是,您可以将它们附加到一个特定的结构,这样每当该特定结构的数据或我们可以说 Base Structure 发生变化时,它都会影响所有其他结构。总体而言,只需在所有其他结构中调用 Base Structure。 例如,参考下面的代码:
struct o{
int data=3;
char name='c';
}one;
struct t{
int data=one.data;
char name=one.name;
}two;
现在,当您调用结构二时,它将打印结构一的数据。