本帖最后由 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()方法。
|