Take the 2-minute tour ×
Arduino Stack Exchange is a question and answer site for developers of open-source hardware and software that is compatible with Arduino. It's 100% free, no registration required.

The author of the PinChangeInt library and the EnableInterrupt library states at github:

When the PinChangeInt was in a .h and .cpp file, the Arduino IDE tried to compile it twice. I have a technique that you can use- #define LIBCALL_ENABLEINTERRUPT - that if you put it ahead of your #include in all files but the sketch, then you should be able to use the library without conflicts. If you know how to make it work in another way- remember, this is a library and will not compile in the same directory as the sketch and any other .h/.cpp/.ino files- then I'm all ears.

I came there, because both libraries failed to build with linker errors due to double definitions. So far so good. I split the PinChangeInt library in .h and .cpp myself and it compiled flawlessly. I did not try to split the other library yet because it looks like much work to me.

So now my question(s): Is GreyGnome right with his statement, that library code gets compiled twice when split in code and headers? And if so, what are the consequences? Memory waste? Runtime errors? What about the many other (working) libraries exhibiting separate code and header files?

share|improve this question
    
I have no clue what he's on about. CPP files only get compiled once. Otherwise the whole Arduino system would fail miserably since most other libraries are split into CPP/H. –  Majenko Aug 30 at 15:40
1  
My guess is that he didn't split the files properly and ended up with duplicate references. –  Majenko Aug 30 at 15:50
    
Ahem, so if I have some time again, I'll try to split this library too. –  Ariser Aug 30 at 16:30
    
As I mentioned in your somewhat related thread the IDE does things in a reasonably understandable way: Classes and objects: how many and which file types I actually need to use them?. –  Nick Gammon Aug 31 at 7:08
    
@NickGammon: I read that already. But how does this help me with that library? Do I have other means than rewriting it? –  Ariser Aug 31 at 12:29

1 Answer 1

Header files are parsed by the preprocessor and the compiler wherever they are included.

There's nothing weird about that. One can avoid multiple inclusions by using header guards. That's pretty standard too.

I have not looked at the library, but, for example, a typical error is to not declare variables as extern in the header and instead leave the real declaration in the header, which will lead to multiple instances, possibly clashing at link time. Variables that are part of the library API should be declared as extern in the header and the real declaration should be done only in the .C/.CPP file.

Interrupts are an even more special case: the AVR gcc relies on very specific names to identify interrupt handlers and each of them can be present at most once. So there are even more chances for having linker problems, if not declared correctly.

share|improve this answer
    
The problem is, that both libraries lack .c/.cpp files entirely. Hence the real declaration is in the header and it is not possiple to declare it extern. The compiler takes the header guards correctly. But the linker throws the double declaration errors afterwards. –  Ariser Aug 30 at 18:44
    
Indeed, what should be done is to split the library into .h and .cpp, so that it can work in a sane way. FWIW, though, using PCINT is trivial, if done without the library, assuming that you only care about one specific platform (say ATMega328p). The library bends backwards several times to cope with the different layout of AVR ports across various ATMega chips. But if all you care about is one chip, you can write much simpler code. –  Igor Stoppa Aug 30 at 18:47
    
On my Interrupts I show how you can use pin-change interrupts in about 4 lines of code. My personal view is that if you are targeting a particular processor it is easier to just write those four lines. By the looks of it you have already spent a number of days to "save the effort" of writing those few lines. The problem is, that both libraries lack .c/.cpp files entirely. - so? Split the file into two files. ... it is not possiple to declare it extern - anything is possible. –  Nick Gammon Aug 31 at 20:41
    
To be fair, the library does more than what is accomplished by those 4 lines. Replicating the same functionality would take a similar amount of code. But it could be done without abusing the header. –  Igor Stoppa Aug 31 at 20:58

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.