Trying to compile. #include madness

35 views
Skip to first unread message

jim...@leftcoast.biz

unread,
Jul 16, 2014, 2:28:59 AM7/16/14
to arduino-pincha...@googlegroups.com
I wrapped your PinChangeInt library into a separate .cpp file in my sketch. But the compiler is going on about multiple definitions of things in there. I think I remember something in the info. about do X if you want to put it in a different file, but I can't find it anymore. Any hints? I'm all ears, well eyes.

Thanks!

-jim lee

Michael Schwager

unread,
Jul 17, 2014, 1:28:16 PM7/17/14
to arduino-pincha...@googlegroups.com

Try defining LIBCALL_PINCHANGEINT (check the source, Luke). Instructions are in the .h file. That makes sure that things are only defined once.

--
You received this message because you are subscribed to the Google Groups "arduino-pinchangeint-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to arduino-pinchangeint...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

jim...@leftcoast.biz

unread,
Jul 17, 2014, 11:45:34 PM7/17/14
to arduino-pincha...@googlegroups.com
I'm sorry, I just don't see/understand what your saying. I did get it to work by just tossing it in with my other sketch files. (At the sketch level) I have been reading about this kind of issue and I think now that it may have nothing to do with your stuff. Arduino IDE seems to be flakey when it comes to #including stuff. Seems to ignore @ifdefs and cause all sorts of nightmares. On every example I've seen, its used in the main sketch. Never have I seen one where it is just used in a .cpp file and hidden there.

But, I do have it working and I'm very pleased with that. I was all worried how I was to get input from an RC receiver. 

Thanks!

-jim lee

jim...@leftcoast.biz

unread,
Jul 17, 2014, 11:58:14 PM7/17/14
to arduino-pincha...@googlegroups.com
Wait! I googled it and found the explanation on 1.70 Beta release. The explanation seems to be missing on the current version.

Now I'd like to know how that actually works so I can used it to make my stuff work better.

Thanks again!

-jim lee

Michael Schwager

unread,
Jul 31, 2014, 11:50:30 AM7/31/14
to arduino-pincha...@googlegroups.com
My remembrance is a little vague at this time, but basically what I think is happening is this:

Say you need to #include a file something.h in your main sketch. Let's also presume you have other .cpp files as part of your project. What happens is: The Arduino IDE copies everything into a temporary directory (on Linux, it's /tmp/build############.tmp, where the "#" signs represent a long string of numbers). Your .ino file is renamed as a .cpp file, so the compiler can do its work as usual. All of your cpp files are compiled to .o files. All of the components defined in the .ccp files are created in the .o files at compile time: code is created, memory is set aside for them, values are assigned, etc. The only thing that remains is to link them all together in the final compile step.

Well: if you #include a file in a .cpp file, it is as if the file was part of the .cpp file. If you define a function in one .o file, and define it in another .o file, at the time linking takes place, how does the compiler know that those functions are one and the same? It doesn't, and it can't. Remember, the Arduino IDE does funky stuff... all the .o files are created separately from each other. So the compiler complains because it finds a function by the same name, defined twice, and it has no way to tell which one you actually want.

I wanted to solve this problem: There are a number of #defines that one can set in one's sketch to modify the behavior of the PinChangeInt library. I could force the programmer to go to another .h file and modify it, but forcing a developer to modify a .h file that was downloaded in a package is a bad practice: This means you must modify it for your particular sketch, but what happens if you come back a month or a year later and reuse the library for another project? Maybe you don't remember that you did something to the downloaded .h. The developer must be able to depend on the contents of the delivered files at all times.

So I think it is more important to allow the developer to #define what they need to in an expected place, and leave the code and its files which were delivered- that is, the library- alone. So I did the ugly thing and put everything in the .h file. Remember, it is ugly mostly to me (the developer of the library) but clean to the sketch writer. I can handle it, because I'm the guy who wrote the library and I should have a deeper understanding of it. So when a developer of a sketch #define's something to modify the library's behavior, and then #includes the library's .h file afterwards, the proper behavior is seen and it is encapsulated in the current project.

However, the problem of compiling the library's functions and variable definitions multiple times remains, if the developer uses the library in another file as part of their project. What I need to do is tell the compiler not to compile everything multiple times: Since the .ino file of the sketch #includes the library, we can rest assured that all components of the PinChangeInt library are compiled already. So I include a directive in the PinChangeInt.h: #ifndef LIBCALL_PINCHANGEINT. So #define LIBCALL_PINCHANGEINT precede #include PinChangeInt.h in every file that #includes it, *except* the original sketch.

But! you say, how do those other files call, for example, PCintPort::attachInterrupt() to attach an interrupt? Again, remember it is safe to assume that the function is going to be compiled correctly- in other words, the machine language code will be written for your sketch. This is done by the compiler when it compiles the .cpp file in /tmp that the IDE copied from the .ino. When a library or other .cpp file is used in conjunction with your sketch, only the *declaration* needs to be known. Remember the difference between a declaration and a definition: A declaration, in source code, says "This is what this <variable, function call> is supposed to look like. Don't worry, it will get a real value later." Notice in PinChangeInt.h where that #ifndef LIBCALL_PINCHANGEINT line takes place: AFTER all the variable and object declarations. Look what happens immediately following the #ifndef: All the static variables in the PCintPort are defined, then the PCintPort's are themselves defined (actually, there is a bit of code there that's in a silly place... I should get that #ifdef FLASH out of there). At the point of *definition*, that's where the compiler actually puts the code into the .o file. All the code that uses those functions or variables are merely assigned a reference to them at the time their .o files are created, it's the job of the linker phase to resolve a reference to, say, PCintPort::attachInterrupt(8, &myfunction, FALLING); . And again, since the function was compiled into machine code by your sketch's .ino file, and since the compiler has that function's location, it is no problem to link to it from .o files that contain references to it.

...I got pretty deep there, but I hope that explains everything.



--
You received this message because you are subscribed to the Google Groups "arduino-pinchangeint-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to arduino-pinchangeint...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
-Mike Schwager

left coast

unread,
Jul 31, 2014, 4:56:26 PM7/31/14
to arduino-pincha...@googlegroups.com
Wow thanks for this! I'd forgotten the issue and was sailing on with life. (Once I got it to work) I wish they'd fix this compiling nonsense in the Arduino. I've been bit by it a lot.

What I've found as an accidental partial  work around was to put my common code in a folder in the Arduino library folder, then let another editor open those files. This happened because I clicked on one and my Xcode app opened it up. I found I could edit and save in Xcode on my common files and the Arduino IDE treated them as library files when it compiled.

Anyway, thanks again for the explanation I really do appreciate it!

-jim lee


You received this message because you are subscribed to a topic in the Google Groups "arduino-pinchangeint-discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/arduino-pinchangeint-discuss/Z-sO1oKd5tc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to arduino-pinchangeint...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages