Go Down

Topic: Using libraries in libraries (Read 1 time) previous topic - next topic

mattallen37

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.

Brad Burleson

#1
Feb 16, 2012, 04:22 am Last Edit: Feb 16, 2012, 04:25 am by Brad Burleson Reason: 1
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:

Code: [Select]
#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

mattallen37

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).

mattallen37

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?

Nick Gammon

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.

mattallen37

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.

Nick Gammon


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:

Code: [Select]
  extern HardwareSerial Serial;  // so it can be referenced in lots of places

In HardwareSerial.cpp:

Code: [Select]

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


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


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

mattallen37

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)?

Nick Gammon

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.

Nick Gammon

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.

mattallen37

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.

Nick Gammon


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".

mattallen37

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

mattallen37

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?

PaulS

Quote
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?

Go Up