Building new library, header, and other library

Hello,

I'm developing my own library and have my basic functions working, header is defined, and I can use the library from my sketch.

Now I want to add the TLC5940 library because I need to use its functions in the .cpp file of my library. I cannot seem to get a clean compile when I try to add the headers ...

include "Tlc5940.h"

include "tlc_servos.h"

Two issues. First was that when including them using above format the compiler just complained that it could not fine the header files. So I changed it to a hardcoded path and that got by that error ...

include "C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940\Tlc5940.h"

include "C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940\tlc_servos.h"

Now I just get a string of nonsense " multiple definition" errors.

Given my sketch "mysketch.ino" My library header "mylib.h" An my source "mylib.cpp"

Where should the includes for the TLC5940 .h files go? The only place I need/want to use the TLC5940 functions is in mylib.cpp file. There is no reference to the TLC functions in my sketch or in the header.

I've tried putting the includes for the tlc in each of my 3 files; then also in multiple locations, but I cannot get a clean compile, always with the "multiple definitions" errors.

Before I started to build the mylib, I had all my code in the sketch including the TLC header lines, and the compile was clean and the program worked. Now I'm just trying to move it all into mylib.

Appreciate any tips, examples of how to use libraries within your libraries.

Thanks!

Hi, compile errors are so f'***ing difficult, because there are so many of them. Even if there is just one variable defined somewhere else you will get that error. The Servo headers should be fine so far. Very smart people developed them and you will not mess up with them.

First: Make sure that your code is protected against multiple includs. Add to your header file in the first two and last line the following code:

#ifndef __my_header_h__
#define __my_header_h__
// here comes your code
#endif

if you already did this, you should rename your variables, to be sure that there are no name conflicts, but when it was running before, that shouldn't be your problem.

It would help if a) you posted your actual error messages, and b) posted your sketch and library code.

Without those we have no hope of helping you.

Also, did you know you can't include a third party library into another library properly? A flaw in the way that the Arduino IDE works means that libraries included in other libraries don't get picked up and compiled into the final executable - you have to include the extra libraries in your sketch as well as in your library.

However, having looked at the tlc library I can confidently say that the library has not been written by competent developers. The tlc_servos.h file is full of complete functions. You never put functions in a header file unless they are inline functions, which these are not. So, if you include the header file more than once (which you have to for the Arduino IDE to pick it up - once in the library and once in your sketch), in multiple target objects (mylib.o and mySketch.o), even with it "protected" with #ifndef etc (which only protects against inclusion within the same source chain), it will never compile, as you're defining the same functions in multiple object files.

Edit: I have raised an issue with the developers

compile errors are so f'***ing difficult, because there are so many of them.

No they aren't. There are lot of them because there are so many ways to write incorrect code. But, the messages are no chosen at random, like fortune cookies. There is a single, specific, message for each syntax issue in the code.

That message was chosen because it means something to someone. Actually, more than one someone, since C and C++ have governing boards that define what is, and what is not, syntactically correct. The compiler writers can add whatever message they like, but those get reviewed, too. There is relatively common agreement that "They sky is a lovely shade of maroon today" conveys no information about the syntax error.

Even if there is just one variable defined somewhere else you will get that error. The Servo headers should be fine so far.

Proper use of include guards, often overlooked (because they are not intuitively obvious) by new coders, solve that particular problem.

As does not putting things in header files that belong in source files.

It's all guesswork what OP's problem is, without seeing ALL the code.

Take heart, OP. What you want to do CAN be done.

Ok, here is my source then. Thanks for looking.

I actually removed all the code from the .cpp functions to make it smaller and easier to read; it does not affect the issue of trying to get it to compile.

For new readers, here is the issue. I’ve trying to setup my own library to include the TLC5940 library and make calls to the TLC5940 routines from my .cpp library source. I don’t need to access the TLC routines from the sketch.

As it is now, trying to compile the code below will spit out a bunch of “multiple define” errors. As you can see in each of my files below, I have the includes present and commented out where I was trying different combinations.

Here is a sampling of the errors; the real list is about 4 times longer.

TTCS\TTCS - Copy.cpp.o: In function tlc_angleToVal': C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:113: multiple definition of tlc_angleToVal(unsigned char)’
TTCS.cpp.o:C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:113: first defined here
TTCS\TTCS - Copy.cpp.o: In function tlc_valToAngle': C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:122: multiple definition of tlc_valToAngle(unsigned int)’
TTCS.cpp.o:C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:122: first defined here
TTCS\TTCS - Copy.cpp.o: In function tlc_getServo(unsigned char)': C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:106: multiple definition of tlc_getServo(unsigned char)’
TTCS.cpp.o:C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:106: first defined here
TTCS\TTCS - Copy.cpp.o: In function tlc_setServo(unsigned char, unsigned char)': C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:99: multiple definition of tlc_setServo(unsigned char, unsigned char)’
TTCS.cpp.o:C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:99: first defined here
TTCS\TTCS - Copy.cpp.o: In function tlc_initServos(unsigned char)': C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:76: multiple definition of tlc_initServos(unsigned char)’
TTCS.cpp.o:C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:76: first defined here

Here is my sketch:

boolean debugPrint = false;

//#include "C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940\Tlc5940.h"
//#include "C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940\tlc_servos.h"
#include <TTCS.h>

TTCS Ttcs = TTCS();

void setup() {
}

void loop() 
{ 
   Ttcs.loop();
}

Here is my library header (TTCS.h):

#ifndef TTCS_H
#define TTCS_H

#include "Arduino.h"
//#include "Tlc5940.h"
//#include "tlc_servos.h"

//had to code full path so compliler would stop complaining about files not found
#include "C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940\Tlc5940.h"
#include "C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940\tlc_servos.h"

#define SERVO_PULSE_WIDTH_USEC   5
#define SERVO_DELAY_TIME      20

#define NUMBER_OF_SHIFT_OUT_CHIPS   2
#define NUMBER_OF_SHIFT_IN_CHIPS   2

struct TTCS_ITEM {
	int     signalPin;
	boolean triggered;
	int     pairedIndex;          
	long    lastTriggered;        
	int     switchPin;            
	byte    switchDirection;      
	byte    flipTrackDirection;   
};

class TTCS
{
  public:
  	int shin_ploadPin;
	int shin_dataPin ;
	int shin_clockPin;


	int shout_clockPin;
	int shout_latchPin;
	int shout_dataPin;

	byte shiftOutData[NUMBER_OF_SHIFT_OUT_CHIPS];
	byte shiftInData[NUMBER_OF_SHIFT_IN_CHIPS];

	int overRidePin;

	long lastLedPulse;
	long ledPulseDelay;

	unsigned long motorFrequencyStart;
	unsigned long motorFrequency;
	unsigned long motorDutyCycle;
	unsigned long lastMotorOnCycle;
	unsigned long lastMotorOffCycle;
	unsigned long motorRunningOn;
	unsigned long motorRunningOff;

	long lastPulseChange;
	long lastAnalogRead;

	boolean servoAngleRising;
	long lastServoPulse;
	long servoPulseDelay;
	int servoAngle;
   
    TTCS();
	void loop();
	void addItem(TTCS_ITEM *newItem);

  private:
	int  pulseWidth1;
	void pulseLeds(void);
	void pulseMotor(void);
	void pulseServos(int servo, int angle);
	void writeShiftOutData();
	void readShiftInRegs();
};

#endif

And here is the stripped down library .cpp source file (TTCS.cpp):

#include "Arduino.h"

#include "TTCS.h"
//#include "C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940\tlc_servos.h"

// Constructor /////////////////////////////////////////////////////////////////

TTCS::TTCS()
{  

       //this is the only call so far in the code that makes reference to the TLC library.
       //Note: I will get the compiler errors with or without this line, so its not the cause of the compile errors.
       tlc_initServos();          
	
	shin_ploadPin           = 11;  
	shin_dataPin            = 12; 
	shin_clockPin           = 13;
	
	shout_clockPin          = 6;
	shout_latchPin          = 5;
	shout_dataPin           = 4;

	overRidePin              = 2;  

	lastLedPulse			= 0;
	ledPulseDelay	 		= 1000;

	motorDutyCycle		  	= 50000;
	lastMotorOnCycle		  = 0;
	lastMotorOffCycle		  = 0;
	motorRunningOn		 =1;
	motorRunningOff		 =0;

	lastAnalogRead		 =0;

	servoAngleRising		  = true;
	lastServoPulse		 	=0;
	servoPulseDelay		  		= 20;
	servoAngle		 		 = 0;
	
	pinMode(shout_latchPin, OUTPUT);
	pinMode(shout_clockPin, OUTPUT);
	pinMode(shout_dataPin, OUTPUT);

	shiftOutData[0] = 0;
	shiftOutData[1] = 255;

	lastPulseChange = millis();
	motorFrequencyStart = micros();
	motorFrequency = 50000; 

	bitSet(shiftOutData[1],6); 
	bitClear(shiftOutData[1],7); 
}

// Public Methods //////////////////////////////////////////////////////////////

void TTCS::loop()
{

}

void TTCS::addItem(TTCS_ITEM *newItem)
{
}


// Private Methods /////////////////////////////////////////////////////////////

void TTCS::pulseLeds()
{
}

void TTCS::pulseMotor()
{
}

void TTCS::pulseServos(int servo, int angle)
{
}

void TTCS::writeShiftOutData()
{
}

void TTCS::readShiftInRegs()
{
}
#include "C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940\Tlc5940.h"
#include "C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940\tlc_servos.h"

Tlc5490 is NOT a core library, and has no business in the core library folder.

TTCS\TTCS - Copy.cpp.o: In function tlc_angleToVal': C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:113: multiple definition oftlc_angleToVal(unsigned char)' TTCS.cpp.o:C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:113: first defined here TTCS\TTCS - Copy.cpp.o: In function `tlc_valToAngle':

What are TTCS - Copy.cpp and TTCS.cpp? You are compiling two files, one of which appears to be a copy of the other. THAT is the problem.

Drats! The "TTCS - Copy.cpp" is a copy of my source library left in the library folder. I created it when I was preparing the source for upload here. It's not the original reason for the errors, it only added a couple more :blush:

Anyways, removed the "copy", using the same source as listed above, and these are the errors.

TTCS\TTCS.cpp.o: In function tlc_angleToVal': C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:113: multiple definition oftlc_angleToVal(unsigned char)' TTCS.cpp.o:C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:113: first defined here TTCS\TTCS.cpp.o: In function tlc_valToAngle': C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:122: multiple definition oftlc_valToAngle(unsigned int)' TTCS.cpp.o:C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:122: first defined here TTCS\TTCS.cpp.o: In function tlc_getServo(unsigned char)': C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:106: multiple definition oftlc_getServo(unsigned char)' TTCS.cpp.o:C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:106: first defined here TTCS\TTCS.cpp.o: In function tlc_setServo(unsigned char, unsigned char)': C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:99: multiple definition oftlc_setServo(unsigned char, unsigned char)' TTCS.cpp.o:C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:99: first defined here TTCS\TTCS.cpp.o: In function tlc_initServos(unsigned char)': C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:76: multiple definition oftlc_initServos(unsigned char)' TTCS.cpp.o:C:\Program Files (x86)\arduino-1.0.3\libraries\Tlc5940/tlc_servos.h:76: first defined here

So from PaulS comment ..."Tlc5490 is NOT a core library, and has no business in the core library folder." ... is that a problem or just a complaint? And what does it mean, not being in the "core library" folder. I'm starting to suspect there's a user library folder I should be using?

Riccarr: So from PaulS comment ..."Tlc5490 is NOT a core library, and has no business in the core library folder." ... is that a problem or just a complaint? And what does it mean, not being in the "core library" folder. I'm starting to suspect there's a user library folder I should be using?

Just a complaint.

The core problem is what I detailed in my first reply. You could manually go through and fix the problems with the library by either making every function that is defined in full in a header file as "inline", or you could split those out into C files which go in a "utility" folder inside the library. The header files would then just contain function prototypes for the functions.

ok, so from your reply#2 I’m getting the jist of the issue; not being able to include a 3rd party lib into another lib. However from PaulS response, “it CAN be done”, so I’m still looking.

Perhaps I will try and extract the TLC routines I need out and put them into my lib, or else embed my routines into the tlc lib.

You can include a library in your library. That is not the problem you are having, though. The library that you include, and your code, must be properly structured, with the class definition or the function declarations in the header file WITH NO EXECUTABLE CODE. The executable code goes in the cpp file.

It's not clear to me, though, which is your library and which is the library you want to include. It isn't clear why the non-core library is still in the core libraries folder.

FYI ... I've resolved my issues.

As PaulS suggests, the executable code in the TLC5940 header was largely the issue. I've moved the TLC library out of the core arduino structure and into "my documents" arduino/library folder tree. I then modified the tlc header to contain just the prototypes and moved the code/functions into the TLC class itself in the main .cpp source.

Now with my own library files in my documents/arduino/library, along with TLC in its own mydocuments/arduino library folder, the includes work cleanly without having to specify the full path, and it all compiles with no errors.

Thanks for the feedback. Cheers, Eric