本帖最后由 kingsing2 于 2019-3-10 11:38 编辑
使用的是Arduino ESP8266 core,版本2.3.0。
问题描述:
在.ino文件中定义一个WiFiClient实例:WiFiClient serverClient
在loop()函数中:
size_t len = Serial.available();
uint8_t sbuf[len];
Serial.readBytes(sbuf, len);
for (i = 0; i < MAX_SRV_CLIENTS; i++)
{
if (serverClient && serverClient.connected())
{
serverClient.write(sbuf, len);
delay(1);
}
}
注意到这里sbuf是个变长度的数组。这段代码的编译不会有问题,即WiFiClient类型的serverClient可以调用write往sbuf里写东西。
但如果将sbuf定义为定长度的,如下:
size_t len = Serial.available();
uint8_t sbuf[100];
Serial.readBytes(sbuf, len);
for (i = 0; i < MAX_SRV_CLIENTS; i++)
{
if (serverClient && serverClient.connected())
{
serverClient.write(sbuf, len);
delay(1);
}
}
编译不通过,WiFiClient类型的serverClient在调用.write()方法时就会有问题。
而如果改成常量的const uint8_t sbuf[100],那么编译就会通过。
问题出在WiFiClient::write(),查看源代码:
template <typename T>
inline size_t WiFiClient::write(T& source, size_t unitSize) {
std::unique_ptr<uint8_t[]> buffer(new uint8_t[unitSize]);
size_t size_sent = 0;
while(true) {
size_t left = source.available();
if (!left)
break;
size_t will_send = (left < unitSize) ? left : unitSize;
source.read(buffer.get(), will_send);
size_t cb = write(buffer.get(), will_send);
size_sent += cb;
if (cb != will_send) {
break;
}
}
return size_sent;
}
发现使用的是模板,代码中有要求使用source.available(),而.available()方法是Stream类型才有的。那么问题来了,为何使用uint8_t sbuf[len] 和 const uint8_t sbuf[100]作为实参传入就没有问题,他们不应该有available()方法呀?
是不是我错过了模板的什么诡异用法?
当然,如果换用Arduino Esp8266 core 2.5.0版本是没有问题的,因为这个版本里不再使用模板来写write()方法。
|