Using libraries in libraries

I am attempting to write a library to simplify some specific I2C related tasks. How can I #include Wire.h in the header file of my library? I don't want to have to #include Wire.h in the main sketch, and I need full access to the functions in Wire.h from my header file (and .cpp file). I have tried many things and googled for about an hour, and I haven't found anything that seems to work.

So I don't know if this is the right way or not, but I took a look at one of the Dallas Temperature IC libraries (from http://milesburton.com/Dallas_Temperature_Control_Library) which also uses OneWire.

Apparently the author has simply included a copy of the OneWire libraries in the same folder as his library, and then simply includes the file:

#include "NewOneWire.h"

(he's using a modified version of the one-wire library)

Have you tried doing that?

Brad (KF7FER)

EDIT: Fixed broken link

Well that does seem to work, although it’s not right.

Another problem: I tried declaring variables in the header file, but it complains about “multiple definition of” them in the .cpp file, and I can assure you I didn’t re-declair them in the .cpp file (although I did use them in functions).

Okay, so now it compiles without errors. I had to add "static" to all the variables. Why is this?

And back to the original problem, how do I properly link to the Wire library?

You shouldn’t have variables in .h files, or you will get multiple declarations. You can put “extern” variables, and then have the real variables in a .cpp file. Making them static just gives multiple copies of variables of the same name, something you probably don’t want.

I think the Wire library can be problematic, from memory of past experiences. The way the IDE copies stuff hither and thither it seems to need an include of Wire.h in the main sketch, seemingly when you shouldn’t need it. Or at least it did under the 0022 version of the IDE.

So, you’re saying I should declare all my library-specific variables in the .cpp file, instead of .h?

What I am doing now, is using #include <Wire.h> in the main sketch, and #include <C:\Program Files (x86)\arduino-1.0\libraries\Wire/Wire.h> in the header file. Why can’t they fix the issues with the files? This is certainly not the only issue.

mattallen37: So, you're saying I should declare all my library-specific variables in the .cpp file, instead of .h?

Yes, the general technique is to put extern foo in the .h file and actually declare foo in the .cpp file in your library.

For example, HardwareSerial.

In HardwareSerial.h:

  extern HardwareSerial Serial;  // so it can be referenced in lots of places

In HardwareSerial.cpp:

// actually create the object:
  HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X);

Why can't they fix the issues with the files?

There are a few issues which "they" have not addressed just yet.

Okay, so what added scope would foo have if I did extern foo in the header (or what scope would foo have without putting it in the header file with extern foo)?

Without putting foo in the .h file it will have scope in the compilation unit in which it resides (ie. the .cpp file).

If it is in the .h file (with extern) it will have scope inside all the compilation units that include it. (In other words, they will get the same foo).

If you make foo static you will get a different foo in each compilation unit. Which isn't particularly useful, I suggest.

Making it "extern" basically says "the linker will sort it out".

But if you never have a "non extern" foo then the linker will say "I couldn't find the real foo" and the link will fail.

So, you're saying that if I want the variables used in .cpp to be global to the entire sketch, I need to prototype them using extern in the header?

And if I don't want them to be global to the entire sketch, I don't prototype them with extern in the header?

In this particular case I don't want them to (at least they certainly don't have to) have scope beyond the library, so is it safe for me to only mention them in .cpp? For what little testing I have done so far, I would say it's working how I want it to without using extern in the header.

mattallen37: And if I don't want them to be global to the entire sketch, I don't prototype them with extern in the header?

Absolutely. And to labour the point, make them static in the .cpp file. If you make a variable static, it can't be "externed" because static says "this is local to this compilation unit".

Thanks a million for the help! Other than the #include Wire thing, it's working exactly how I want it to XD

So everything is still working fine, other than the #include file stuff…

I have a new problem. I built a library that involves timer interrupts. I #include <avr/io.h> and <avr/interrupt.h> from the main sketch, and that work fine (although I would like them to be automatically #include d from the library .h file). I have 4 functions that I don’t want public, and I have 3 that I need public (public, as in accessible from the main sketch). I want to use a Class with Public: and Private:, but I don’t know how to make the ISR be able to access functions in a class.

Would it be best to have all the functions that ISR ever calls, not be in a class (but still private somehow), and put all the sketch-accessible functions in the Class?

It would be ideal to be able to have the ISR call functions from inside a class. Is that possible?

It would be ideal to be able to have the ISR call functions from inside a class. Is that possible?

Sure. But, for which instance of the class?

In other words, you may need to use a static class function.

It is a library that relies heavily on timer 1, and uses IR. Thus, it won't be necessary to have multiple instances (as far as what I understand an instance to be).

Please be specific about how to do it. I have only ever used classes before with the Arduino, and I'm still learning how they work.

You probably don't need a class then. Generally speaking, classes are for multiple instances of things. Like a game might have a monster class because there are lots of monsters that behave in similar ways.

You can have functions in your library file, and those functions that are "external" (ie. not private functions) can be exposed by putting them in the .h file.