Apologies if this has been covered elsewhere but couldn't seem to find something specific about consensus for migrating libraries to 1.0.
I have several libraries that I'm now looking to move to 1.0 given the official release recently. Given that there will probably be a lag on people upgrading (eg currently no binary upgrades in Debian or Ubuntu for auto-upgrading) I want to ensure I have a version that will work in Auduino 0023 (and similar) for at least a period of time.
My current thinking is to simply take my current code, move working versions across to a pre-1.0 folder or preface the files with that and then the default code will work in 1.0
You could conceivably make them branches in git, but that sure makes it harder for people to find if they're not used to git branches. You could prepare two separate downloads of course, SuperLib.zip and SuperLib-1.0.zip.
I was sort of leaning towards the #if arduino < 100 option however the readability suffers a lot when you have code that is making use of the changes (eg .write instead of .print changes etc).
I think as there appears to be no real "correct" method that a combination of the below is probably the way to do it with the git branches + downloads being the way to deal with the most "messy" of cases where there's a lot of changes.
The #if option can produce unreadable code. I suggest if you have two many in a given function (ie > 2-3 probably) that you have two versions of the function and wrap them in an #if. That way each one is readable.
The above code, when compiled in 1.0, only works with the type case (uint8_t) but works without it in 0022. I traced the library code to the following:
The cause here is something SUPER subtle. It really should never have worked. The full text of the error message is listed below. Indeed, it tells the truth. It cannot tell if you mean to call 'write' with '0' as a uint8_t or 'write' with '0' as a null pointer.
something.pde:66: error: call of overloaded ‘write(int)’ is ambiguous
/opt/Arduino/master/libraries/LiquidCrystal/LiquidCrystal.h:82: note: candidates are: virtual size_t LiquidCrystal::write(uint8_t)
/opt/Arduino/master/hardware/arduino/cores/arduino/Print.h:49: note: size_t Print::write(const char*)
This is going on my list of interview questions The super subtle difference is that in 1.0, Print::write(const char str) is no longer virtual. In 0022, it's virtual. So in 0022, the compiler is trying to resolve what you mean by LiquidCrystal::write(0). As there is only one method actually declared as a LiquidCrystal member, it can pick write(uint8_t). It can de-prioritize the virtual write(const char) that is only in the base class. However, in 1.0, it's more confusing, because write(const char*) is a first-class member of LiquidCrystal due to it not being virtual. So the compiler's choice is no longer obvious.
Anyway, you're in the clear for library compat. Just use (uint8_t)0 and you'll be safe in both cases.
Quite a bit subtle here. I guess this is the actual difference:
Print.h in 0022
virtual void write(const char *str); // Not defined in LiquidCrystal.cpp so unusable by compiler
Print.h in 1.0
size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); } // Defined in base class so useable by compiler
So the write method with a pointer as parameter is actually NOT a virtual method and has its code, ALTHOUGH, it calls a virtual method (write(const uint8_t *buffer, size_t size)) that is not defined in LiquidCrystal.cpp of either version.
So this little bug is making the compiler ponder whether to call write (const char *) or write (uint8_t), only when a zero is supplied, because other numbers would only be valid when converted into uint8_t, not a pointer but zero is OK for both types?! Just checked with other numbers and it compiles in 1.0 without (uint8_t). Am I passing your interview-round 1? BTW, what is the meaning of _t? I can understand the unsigned 8-bit integer part but not the _t. Thanks!
liudr:
Print.h in 0022
virtual void write(const char *str); // Not defined in LiquidCrystal.cpp so unusable by compiler
So the write method with a pointer as parameter is actually NOT a virtual method and has its code, ALTHOUGH, it calls a virtual method (write(const uint8_t *buffer, size_t size)) that is not defined in LiquidCrystal.cpp of either version.
Not quite. When the compiler is working on your sketch file, the one with "LCD.write(0)" in it, it doesn't know about LiquidCrystal.cpp or Print.cpp for that matter. It only knows what the headers tell it. Print::write(const char*) is definitely a virtual function. It says so right there in the header
liudr:
BTW, what is the meaning of _t? I can understand the unsigned 8-bit integer part but not the _t. Thanks!
C99 defined standard fixed-size types, including uint8_t. The suffix "_t" has long been taken to designate a symbol which represents a type. I've never actually seen a written standard which said so, but that's the convention. The idea behind it, and any naming convention really, is so that you can look at a symbol and KNOW what kind of symbol it is. The extreme of this is Hungarian notation, which seems to have fallen out of favor a bit.
Anyway you could do something like this:
typedef unsigned long something_t;
something_t something;
... to define variable 'something' to be an instance of 'something_t'.
BTW, Serial.write(byte) (and other Print sub-classes) should work in 0022 /0023 as well as 1.0. So if you have code that currently does Serial.print(n, BYTE), you should be able to change it to Serial.write() and maintain compatibility.
mellis:
BTW, Serial.write(byte) (and other Print sub-classes) should work in 0022 /0023 as well as 1.0. So if you have code that currently does Serial.print(n, BYTE), you should be able to change it to Serial.write() and maintain compatibility.
Great! Thanks. I'm not using print(n, BYTE) but I'll write a blog post on how to do the library conversion with what you mentioned above. I'm sure someone will need to do it for some libraries.