I'm curious to know why libmaple_types.h exists when it duplicates the available c99 stdint.h types...?
Thanks,
SB
I'm curious to know why libmaple_types.h exists when it duplicates the available c99 stdint.h types...?
Thanks,
SB
Regardless what you call them, they still represent the same fundamental datatypes.
The c99 standards require a _t
suffix to each type. libmaple's libmaple_types.h
doesn't include this as an alternative name for the types -- some people don't like writing the _t
. I do -- LeafLabs may not.
How do you pronounce Tomato? Is it still the same fruit?
English pronunciations and code portability are unrelated.
Using libmaple_types.h is a deviation from the ISO C99 standard, resulting in less portable/maintainable code.
#include <stdint.h>
and your problem is solved.
Not quite - ScottyB is right about the portability & maintainability issues. Specifically when you want to start unit/component/end-to-end testing code on other systems because it's faster & easier to debug, plus it is less error prone.
At our office, we develop for several different 32-bit machines, but run unit tests on 64-bit machines. Using the correct values throughout the code can make a big difference when you're tracking down issues.
schmidtw - The C99 type names are of the form int8_t, unit32_t, and are in stdint.h, as the standard defines.
Arduino has used int8, etc., with no '_t' suffix for many years. These are different names from C99. Including libmaple_types.h will not clash with stdint.h names.
LeafLabs try to be compatible with Arduino so that folks can port Arduino-based code across to Maple. I believe LeafLabs have provided those Arduino-style type names in a file with a file-name that does not clash with a C99 name.
So it seems appropriate that both sets of type names exist; the C99 names are in the correct file, and the Arduino-style names are in a file with a name that does not clash with C99.
How else should it be done?
(Full disclosure: I am not a member of LeafLabs staff.)
That's as good a reason why it was done as any.
It would be better to define them in terms of stdint.h types. That way code that is written using all the stdint.h types are always compatible & the libmaple code is more portable.
typedef unsigned int uint32; ---> typedef uint32_t uint32;
schmidtw - "It would be better to define them in terms of stdint.h types" - What do you mean by better?
IIRC deriving int32 from int32_t doesn't give any extra type compatibility; uint32 and uint32_t are already type compatible in the form that they are currently defined. So AFAIK there is no need libmaple_types.h to include stdint.h and typedef from those typedefs to get type compatibility.
On the converse, if libmaple_types.h includes stdint.h (to get 9 typedef names), then that creates an extra dependency for no technical benefit, and some bloat. So, I would suggest that portability is not improved because more files need to be installed to do anything.
Worse, when building on a host system, you need to worry that the host platforms stdint.h might interact in a different way from the Maples.
So, sorry to be contrarian, but I think defining libmaple_types.h by including stdint.h is not better.
Not sure why a body should not define both so that they work.
most of my code uses the std style and a lot of it is coming over from the arduino so I find myself often doing
#ifndef uint8_t
#define unsigned char uint8_t
...
... uint32_t
#endif
I personally find the 3 "standards" annoying but if you have to have them the preprocessor makes it pretty possible to make it just work regardless of which standard you pick (preprocessing is not bloat). Seems like something that should get fixed if and or when the wiring and lib maples folk ever do merge.
feurig - "Not sure why a body should not define both so that they work."
I'd go further and say it should be possible to use any permutation. There should be as few constraints, and hence few dependencies as practical. So I am happy to have them in independent files.
By 'bloat' I mean every time an include file includes a further file (instead of being self-contained), then:
a. that extra file needs to be distributed (source bloat, but not much)
b. the compiler has to parse it which is compile-time bloat (small, but see the rationale for Go-lang; ill-considered dependencies really can cause problems)
c. I sometimes build and test Maple code on my Mac. So I want as few dependencies, which might interact with the Mac C compilation environment as I can, or I may need to build a special copy of the host platform includes to support Maple builds (bloating my work, and space bloat).
I do include stdint.h if I need those typedefs. stdint.h defines about 80 typedefs and macros. libmaple_types.h has 9 typedefs and 3 macros.
I believe typedef
is done by the compiler not the pre-processor; pre-processor does #define replacement, but a typedef (say for a function which takes some parameters, say typedef void (*voidFuncPtr)(void)
) can't always be handled by textual replacement.
What I meant by better is that by making the two the same & simply aliasing the definition you wish to use enables full compatibility at all times. Depending on the hardware and compiler combination the definitions of what an int32_t is can change.
For example, on one piece of hardware I routinely develop on (using a non-gcc compiler), int32_t is defined as:
typedef long int32_t; /* 32 bits on one machine, but can be 64 bits on another. */
typedef int int32_t; /* 16 bits on one machine, but can be 32 bits on another. */
stdint.h should not be distributed as part of any software package except the compiler. If your compiler doesn't, you probably want to find a new compiler because the odds are it isn't doing other things you expect it to.
Another value of stdint.h is intptr_t - which is extremely helpful when pointers and integers are not the same size. The main uses where I've used this are around c mock objects (for testing), and lower-level OS functions. Again the big win is I can develop code and run the code on a 64-bit machine & I run into fewer issues with incompatible sizes.
Standards are generally standards for a reason & help solve common problems - especially expensive ones that may come in the future. My goal is to help make this cool looking framework better, that is all.
schmidtw - I don't think you understand my points:
1. defining int32 as typedef int32_t int32;
does not make those two types any more (or less) compatible than the current independent definitions in lib_maple.h - so there is no technical improvement.
2. There is a need for int8
, int16
, int32
for Arduino software. These are not part of C99, so they can be defined in anyway that is sensible. They could be derived from stdint.h, but they don't need to be.
There are only 9 typedef names in lib_maple.h. The stdint.h packaged with Maple's IDE creates about 80. Those extra names may have been used by someone writing code that I'd like to port. I would prefer to control non-standard names independently from standard-specified names. You might not have tried to do this sort of thing, but it can be extremely tedious to remove names defined in standard header files which clash with source code if there is a need to minimise changes to source.
3. Worse, changing lib_maple.h requires work for no benefit (that you've explained yet), and could introduce an error. It is antithetical to modern development approaches to do work for no benefit, and to risk introducing an error.
So, unless you can explain where we get benefit from making the change, it all looks like down-side.
What is the use-case for changing lib_maple.h where their is benefit that outweighs any cost?
Standards can be beneficial, when used wisely. I like using standards whenever it's a good solution.
IMHO it is naive to believe standards provide answers to all questions, or that they are the only solution. Nor are they perfect, as you can discover by tracing the changes between language versions, or the inaccurate or poor implementations (for example look at widely used, but poor regex implementations used). Nor are the reasons they exist necessarily to solve technical problems, for example the accusations of 'stuffing' the standards bodies, suggest there is more than solving common problems.
Something simple, and direct can be a good solution.
Of course gcc provides stdint.h - you can go learn about them by downloading gcc source from http://gcc.gnu.org/
As you can see, there are three stdint.h files and several files they depend on; well over 600 lines.
Those gcc stdint.h are not packaged in the Maple-IDE. Instead the stdint.h from newlib is used.
IMHO this is just as appropriate as the gcc stdint.h because newlib is the implementation of the standard C library supplied in the Maple IDE packages, and is widely used by microcontrollers, regardless of the compiler.
If you want to use intptr_t in code, just #include <stdint.h>
- job done. It is available, independent of lib_maple.h
Having a lib_maple.h doesn't restrict your options.
I'd recommend using uintptr_t because memory addresses usually are unsigned values; overflow has a different meaning for signed numbers, and could happen when an address gets its top-bit set after arithmetic. Worse, on some processor architectures signed and unsigned have different behaviour.
Since it looks like there isn't any framework for unit or component tests, then the 9 line change probably doesn't buy as much.
Thanks for your feedback, it has been helpful in understanding the project design philosophy and goals.
schmidtw - please don't misunderstand; as I wrote, I am not a member of LeafLabs staff, so all opinions are mine, and not LeafLabs.
I have been using Maple for a few years, designed and built a board derived from Maple, but also use ST Micro's discovery boards.
For some insight into where LeafLabs say they are going with the software, these blogs might help:
http://leaflabs.com/2011/11/were-teaming-up-with-wiring/
http://leaflabs.com/2012/06/major-update-experimental-stm32f2-and-f1-value-line-in-libmaple-master/
http://leaflabs.com/2012/07/libmaple-new-include-style-on-the-way/
Most of libmaple is peripheral interface code. Testing that stuff often involves an oscilloscope, signal generator, or second processor board. So it is a bit more of a challenge to test than automated unit tests on pure software.
That isn't to say that it could not be better tested, just that the example programs included with the IDE often end up being the easiest way to test the library, and those tests often have a human, and maybe test equipment, in the loop.
I'm dealing with multiple platforms and that kind a singularity is really annoying.
I hope the new Wiring is going to solve those idiosyncrasies.
For me, I can hardly use my Maple board due to this differences and the lack of basic libraries as string and stream.
You must log in to post.