-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Compile error on Linux due to new File::write function #5846
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
* Add a FAT filesystem for SD cards to Arduino FS Arduino forked a copy of SD lib several years ago, put their own wrapper around it, and it's been languishing in our ESP8266 libraries ever since as SD. It doesn't support long file names, has class names which conflict with the ESP8266 internal names, and hasn't been updated in ages. The original author of the SD library has continued work in the meantime, and produced a very feature rich implementation of SdFat. It unfortunately also conflicts with the class names we use in ESP8266 Arduino and has a different API than the internal SPIFFS or proposed LittleFS filesystem objects. This PR puts a wrapper around the latest and greatest SdFat library, by forking it and wrapping its classes in a private namespace "sdfat," and making as thin a wrapper as possible around it to conform to the ESP8266 FS, File, and Dir classes. This PR also removes the Arduino SD.h class library and rewrites it using the new SDFS filesystem to make everything in the ESP8266 Arduino core compatible with each other. By doing so it lets us use a single interface for anything needing a file instead of multiple ones (see SDWebServer and how a different object is needed vs. one serving from SPIFFS even though the logic is all the same). Same for BearSSL's CertStores and probably a few others I've missed, cleaning up our code base significantly. Like LittleFS, silently create directories when a file is created with a subdirectory specifier ("/path/to/file.txt") if they do not yet exist. Adds a blacklist of sketches to skip in the CI process (because SdFat has many examples which do not build properly on the ESP8266). Now that LittleFS and SDFS have directory support, the FS needs to be able to communicate whether a name is one or the other. Add a simple bool FS::isDirectory() and bool FS::isFile() method. SPIFFS doesn't have directories, so if it's valid it's a file and reported as such. Add ::mkdir/::rmdir to the FS class to allow users to make and destroy subdirectories. SPIFFS directory operations will, of course, fail and return false. Emulate a 16MB SD card and allow test runner to exercise it by using a custom SdFat HOST_MOCK-enabled object. Throw out the original Arduino SD.h class and rewrite from scratch using only the ESP8266 native SDFS calls. This makes "SD" based applications compatible with normal ESP8266 "File" and "FS" and "SPIFFS" operations. The only major visible change for users is that long filenames now are fully supported and work without any code changes. If there are static arrays of 11 bytes for old 8.3 names in code, they will need to be adjusted. While it is recommended to use the more powerful SDFS class to access SD cards, this SD.h wrapper allows for use of existing Arduino libraries which are built to only with with that SD class. Additional helper functions added to ESP8266 native Filesystem:: classes to help support this portability. The rewrite is good enough to run the original SDWebServer and SD example code without any changes. * Add a FSConfig and SDFSConfig param to FS.begin() Allows for configuration values to be passed into a filesystem via the begin method. By default, a FS will receive a nullptr and should so whatever is appropriate. The base FSConfig class has one parameter, _autoFormat, set by the default constructor to true. For SPIFFS, you can now disable auto formatting on mount failure by passing in a FSConfig(false) object. For SDFS a SDFSConfig parameter can be passed into config specifying the chip select and SPI configuration. If nothing is passed in, the begin will fail since there are no safe default values here. * Add FS::setConfig to set FS-specific options Add a new call, FS::setConfig(const {SDFS,SPIFFS}Config *cfg), which takes a FS-specific configuration object and copies any special settings on a per-FS basis. The call is only valid on unmounted filesystems, and checks the type of object passed in matches the FS being configured. Updates the docs and tests to utilize this new configuration method. * Add ::truncate to File interface Fixes #3846 * Use polledTimeout for formatting yields, cleanup Use the new polledTimeout class to ensure a yield every 5ms while formatting. Add in default case handling and some debug messages when invalid inputs specified. * Make setConfig take const& ref, cleaner code setConfig now can take a parameter defined directly in the call by using a const &ref to it, leading to one less line of code to write and cleaner reading of the code. Also clean up SDFS implementation pointer definition.
@TD-er Can you try with this small patch ?
|
I tested it and as expected it now has even more options to choose from, so it is even more ambigue :)
|
I'm not sure if it is worth the trouble, but you can use these template things to make the function parameters strongly typed. But I guess it could be used on the newly added |
And please do not use 'old-style' cast in C++ |
@TD-er then add
@Barracuda09 following your comment I just read this discussion (there are tons like it). TBH, I don't see why the above code is wrong. We are dealing with basic scalars here, and we need to tell the compiler how to redirect overloaded calls.
I don't know which of Please have a look to edit: |
That is the whole idea, you have to think about it (and not let the compiler make a choice) but in this case a static_cast would do. But looking at the code and 'patch' make me think something else is not adding up |
This is enough for me to make it compile:
|
@TD-er I don't understand your use of @Barracuda09 (or any c++ advisor) is it an acceptable c++ way of casting:
Here we use a constructor, it is not C-way and we can exactly and explicitly understand what it does. |
About the casts, when calling it via the constructor, you're creating somewhat of a deepcopy of the data (depending on the copy constructor of the object of course) But in general the main advantage of using casts is that you're doing it on the existing object. About the template part. Yep that was needed to instruct the compiler to consider those definitions of |
@TD-er |
I can't think I understand About And I just don't understand the reason of the existence of My point is to avoid using magic words when they are obscur. One could tell me that we must know the langage, and that's true. But still, you must always know what you are doing.
I still don't understand. There's no code for it and you later explicitly defines -- in the quest for coherency and truth :) edit: @jfbastien there's an occasion to guide the blinds to the light if ever you deign looking to this |
A very short reply, since I have to go and pick up my daughter from school... The The other points you mention also deserve a proper reply, but maybe someone else can explain the C++ details better than me (and I have to go now) |
@d-a-v consider this code const char *c = "Hello World";
They are not more magic then if/switch/struct etc if you know the C++ language Edit: sorry the code was corrupted |
So, short story with 'old-style' cast you let the compiler decide wat he thinks your intension is |
What I'm trying to say is that
I'm still looking for good reasons to not think like this. |
'old style' cast can do this also if you let the compiler decide... But it is not traceable
That should not be, because it is something unusual (don't say it is more typeing then you use also an 'old-style' editor)
Well these are not cast they are constructors, BUT do not use int(x) that does not make sense
performence is indeed debatable. But the hole idea is that you can traceback these anomalies in the code. With 'old-style' it is not. |
It seems more right to me to say that |
Sorry, You lost me here |
Alright, in the words of my countrymen: "Somebody has to cut the cake".
There are only a very few cases where one would want to cast away a const qualifier, and in those cases it is better to be made explicit to show that it is on purpose. Hence, use of const_cast<>() is better in such a cases. dynamic_cast<>() should be used only with polymorphic classes. reinterpret_cast<>() exists for memory transformations. The use case is similar to a union, where you write to one type and read from the other type. Example:
Again, this is meant to make the intent explicit: I am taking an address to an unsigned int, and interpreting the data it points to as something different. static_cast<>() is meant to replace the typical intent of old C-style cast, while disallowing unintended cases like casting away the const qualifier. For casting between different sizes of integer, this would be appropriate. So, yes: the *_cast<>() versions
|
Now, let's get the thread back to the original issue reported here, which is the overload ambiguity. |
To be clear, my previous explanation is the general explanation and recommendation. |
My mind tells me From Bjarne Stroustrup:
Thank you to help me discovering this today :) @Barracuda09 you are free to make a PR, I am no authority here ! |
Well I am still learning as well, and I am far from a teacher. So I want to apologize for my approach. |
Don't. I am a part-time c++ teacher, so if there are good arguments to convince me, do it quick, because I would otherwise spread evil knowledge ;-) |
@TD-er ESPEasy is calling The correct thing to do is to explicitly call with a supported overload, like one of the following:
*Notice that there seems to be a bug in the core, because the new |
While I agree, I'm afraid ESPEasy's issue is only the first one with this API change. |
I totally agree on the ugliness of that part of the code and I am also willing to change it, but like @d-a-v suggests, it may lead to a lot of other projects failing. As a quick work-around I already copied the byte to be written to a new N.B. Before trying to fix it, I also tried to |
Arduino base class Print has 4 write functions:
and it works |
@JAndrassy Have you already tested it like that? |
Trying one more time to convince you (Last attept). Look at this code:
So please rethink and try to use *_cast<> |
* Reimplement SD.h write methods exactly in File Replace the individual override with the existing SD.h File's implementation for all methods of File::write. Fixes #5846 * Add add'l tests * Fix Print and File incompatible writes w/casts Print and File have ambiguous resolutions for single-argument write(0)s. Fix by adding explicit methods. A write of any integer will not be a const char* write (i.e. won't write a string) but will instead just write the integer truncated to 8 bits (as makes sense). * Use 256byte chunks in ::write template Reduce stack requirements for templated writes to 256bytes, matching the size uses in WiFiClient/etc. (from 512bytes). Reduces the chance of stack overflow. * Move write(int) methods up to Print.h Remove some technical debt by moving the ::write(int/short/long) methods out of FS and HardwareSerial and up into Print.h.
The last change made the error move to another class, the write part of HardwareSerial.
For ESPeasy I will fix it, but it may be others will also report some similar issues. |
@devyte , did we get the hierarchy wrong? I don't think so, Print -> Stream -> (HW Serial, FS). So wouldn't the write methods at the lower level disambiguate at the uppermost one? |
Please note that the Travis output this error appeared in was still having the changed code I added to work around the previous issue. |
I have added host tests which include File.write(0) (and others), so I feel pretty confident that bit works. But there's obviously no HWUart host tests, so that wasn't tested. The class was just missing the "using" statement. Manual checks show Serial.write(0/other ints) and (C-string) look good now. |
Great, then I will restart that Travis build, so we'll see :) |
This issue has been closed, but it has not been fixed. |
#5878 is supposed to have fixed it. Please try latest master, and open a new issue with your details. |
Multiple libraries were found for "SdFat.h" |
See also this discussion: b1da9ed#r32622483
@devyte asked to open an issue about this.
In pull request #5525 there has been a new function added to the
File
class:Arduino/cores/esp8266/FS.h
Lines 82 to 83 in b1da9ed
This function causes compiler issues on Linux.
In short, this new function makes it impossible to use the existing function
write(uint8_t)
Arduino/cores/esp8266/FS.h
Lines 55 to 56 in b1da9ed
The text was updated successfully, but these errors were encountered: