[solved] how to call a class from my own library, inside another own library

Hi all, I hope you could help me people

I'm working inside my "Cpu.cpp" file library, and it has an "#include <CpuOutputs.h>' as a library dependency. The arduino program (.ino) only has to use Cpu library, because CpuOutputs function is to support Cpu and no more. So .ino program only includes Cpu.h

The problem is, when I try to use CpuOutputs inside Cpu.cpp, I create a CpuOutput object form his own class, using respective consturctor, and:

1: If I only include Cpu.h into my .ino program, an error appears in Cpu.cpp: "CpuOutput is not recognized as a type"

2: If I include CpuOutput.h into .ino program, then there's no error. But I don't want to include it, because It must be a Cpu dependency, not for use in .ino program

Code from dependency CpuOutput library (not necessary, it runs ok, but I show the basics):

// CpuOutput.h
#include <inttypes.h>
#ifndef CpuOutput_h
#define CpuOutput_h

class CpuOutput{
public:
// Constructor
CpuOutput(uint8_t LatchPin, uint8_t ClockPin, uint8_t DataPin);
// Destructor
~CpuOutput();

void digitalWrite(uint8_t pin, uint8_t value);
....
};
#endif

Code from dependent Cpu library (the important part):

// Cpu.h

#if(ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#endif

#include <CpuOutput.h>
#include <inttypes.h>

#ifndef Cpu_h
#define Cpu_h

class Cpu{
public:
// Constructors
Cpu();
Cpu(uint8_t p1, uint8_t p2, uint8_t p3, uint8_t p4 = 0);

// Destructor
~Cpu1284();
private:
// Constructor arguments
uint8_t lcdEnabled;
uint8_t encoderEnabled;
uint8_t motorEnabled;
uint8_t digitalInputsSector1Enabled;

// Internal variables
CpuOutput extendedOutputSector3;

// Internal functions
void enableMuxPins();

// Digital Output pins sector3
uint8_t d22; // latchPin
uint8_t d23; // clockPin
uint8_t d0; // dataPin
};

#endif

// Cpu.cpp

#if(ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#endif

#include "Cpu1284.h"
#include <Cpu1284ExtendedInput.h>
#include <Cpu1284ExtendedOutput.h>
#include <inttypes.h>

// CONSTRUCTORS
...

// Constructor to be used in .ino arduino program
Cpu::Cpu(uint8_t p1, uint8_t p2, uint8_t p3, uint8_t p4){
lcdEnabled = p1;
encoderEnabled = p2;
motorEnabled = p3;
digitalInputsSector1Enabled = p4;

enableMuxPins();
}

void Cpu::enableMuxPins(){
// Activate digital Output Mux pins from Sector 3
d22 = 22;
d23 = 23;
d0 = 0;
pinMode(d22, OUTPUT);
pinMode(d23, OUTPUT);
pinMode(d0, OUTPUT);
extendedOutputSector3 = CpuOutput(d22, d23, d0);
}

// Function to be used in .ino arduino program
void Cpu::digitalWrite(uint8_t pin, uint8_t value){
extendedOutputSector3.digitalWrite(pin, value);
}

Cpu::~Cpu(){
}

critical code is in bold mode

Thanks

Are the class files in the same directory? I would guess they aren't. Since they are custom libraries, the compiler won't know it has to include the directory containing the CpuOutput library unless you put the #include in the .ino file. That would explain, not solve your problem, but if CpuOutput is not intended to be used standalone you may try using the same directory for both classes.

The arduino program (.ino) only has to use Cpu library, because CpuOutputs function is to support Cpu and no more. So .ino program only includes Cpu.h

That's not supported by the arduino IDE. You'll have to include CpuOutputs.h in the .ino

alternatively if you are writing both and distributing both classes together you can put it in a directory called "utilities" (the Wire library does this, for example)

Thanks Spatula and WizendedEE for your answers

So, if I don't want to include CpuOutput library into .ino file, how I have to restructure the directories? I mean:

I have right now the following directory libraries: ../sketchbook/libraries/Cpu and ../sketchbook/libraries/CpuOutput, just like all other libraries

Considering that CpuOutput is an exclusive dependency for Cpu:

Where should I place CpuOutput? ../sketchbook/libraries/Cpu/CpuOutput? or Where should /utilities directory be placed? It must have CpuOutput inside (/utilities/CpuOutput)?

Thanks

Well, it's up to you. I would put all files in the sketchbook/libraries/Cpu directory, but I might as well change my mind later and put the CpuOutput files in the utility subdirectory, sketchbook/libraries/Cpu/utility. I also think you should include the class using quotes (#include "CpuOutput.h") instead of angular brackets.

This is how it should be, where "arduino" is the sketchbook directory

arduino/libraries/Cpu/
arduino/libraries/Cpu/Cpu.h
arduino/libraries/Cpu/Cpu.cpp
arduino/libraries/Cpu/utilities
arduino/libraries/Cpu/utilities/CpuOutput.h
arduino/libraries/Cpu/utilities/CpuOutput.cpp

Thanks a lot for the answer, now arduino knows where the libraries are

But now I have more troubles, I can not initalize a CpuOutput object properly in Cpu class:

If I write 'CpuOutput outputObject;' in Cpu.h file as a variable, to use in Cpu.cpp (I don't even call it on Cpu.cpp yet), It does not compile having the following error:

undefined reference to `CpuOutput::~CpuOutput()'
undefined reference to `CpuOutput::CpuOutput()'

Seems like is waiting for the constructor?

If I write 'CpuOutput outputObject(); in Cpu.h (calling constructor, with the intention to use it as a CpuOtput variable to use his own methods). It complies (I guess compiler detect that correspond with CpuOutput constructor). But when I try to use it in Cpu.cpp, no matter how I try to use 'outputObject', I have always the same errors calling his .setParameters function (maybe cause don't recognize it as a cpuOutput variable, but as a function):

attemp and error:

outputObject.setParameters(d18, d19, d20, d21, a1, a0);
error: ‘((Cpu*)this)->Cpu::outputObject’ does not have class type

So, create a member variable = CpuOutput constructor not found, and calling constructor = there's no object to use with, cause this is a function? I'm right understanding the errors?

how can I use a CpuOutput object inside Cpu class? or in a general mode, using a class2 object inside class1, considering above errors?

Very grateful for your interest, I wish one day I could help others too

Cpu.cpp does not include Cpu.h, this may cause problems.

CpuOutput outputObject;

It should be in the cpp or declared extern, if you want it in the header, the compiler may also need CpuOutput.h to be included in the header.

CpuOutput outputObject();

This is incorrect as it is a function prototype, taking no parameters and returning a CpuOutput object.

Sorry for de syntax, #include Cpu1284.h is actually the include for Cpu.h, it's an error caused by change my real code in order to show us a easier and summary code. So Cpu.cpp has the Cpu.h include, and the "CpuOutput outputObject;" error still exist

Can someone help me?

That compiler error means that you're calling CpuOutput's no-argument constructor, but it doesn't exist. That's because you are never giving it arguments. Google for "c++ initializer lists" They're a way of passing arguments to the constructor of an object inside a class. Here's an example:

class inner {
public:
  inner(int ii) : i(ii) {} // This is equivalent to...
  // inner(int ii) {i = ii;}
private:
  int i;
};

class outer {
public:
  outer() : in(3) {} // Passes 3 to the constructor of inner
private:
  inner in;
};

class outerWithMultiple {
  outerWithmultiple() : in1(18), in2(393) {} // passes 18 and 383 to the constructors for in1 and in2
private:
  inner in1;
  inner in2;
};

I've been working in my classes considering your example WizenedEE, and I have the following error situations:

At Cpu.h

#include "utilities/CpuOutput.h"

class Cpu{
	public:	
		Cpu();
        private:
                CpuOutput outputObject;

At Cpu.cpp

If I write this:

#include "utilities/CpuOutput.h"

Cpu::Cpu(): outputObject(){}

Arduino generate this error ( at line of Cpu::Cpu(): outputObject(){} ):

undefined reference to `CpuOutput::~CpuOutput()'

Alternatively, if I write this at Cpu.cpp:

#include "utilities/CpuOutput.h"

Cpu::Cpu(){
        cpuObject();
}

Arduino generate this error ( at line of cpuObject(); ):

no match for call to ‘(CpuOutput) ()’

Otherwise, If I don't modify Cpu.cpp at all, and I write this on Cpu.h

#include "utilities/CpuOutput.h"

class Cpu{
	public:	
		Cpu(): outputObject();
        private:
                CpuOutput outputObject;

Obviously, I have the error:

expected `{' at end of input

So I can't initialize an object properly yet. I don't know what else to do

If I write this:

#include "utilities/CpuOutput.h"

Cpu::Cpu(): outputObject(){}




Arduino generate this error ( at line of Cpu::Cpu(): outputObject(){} ):
undefined reference to `CpuOutput::~CpuOutput()'

Did you define a destructor? Did you implement the destructor?

Alternatively, if I write this at Cpu.cpp:

#include "utilities/CpuOutput.h"

Cpu::Cpu(){
        cpuObject();
}




Arduino generate this error ( at line of cpuObject(); ):
no match for call to ‘(CpuOutput) ()’

As well it should. That is NOT how to create an instance of the class. You NEVER call the constructor directly.

So I can't initialize an object properly yet. I don't know what else to do

How about doing what was suggested from the very beginning - post ALL of your code.

If CpuOutput has a no argument constructor, then creating an instance in the Cpu class is trivial. In the Cpu.h file, put

   CpuOutput cpuThingy;

When the Cpu class is instantiated, the CpuOutput constructor will be called to initialize cpuThingy.

If it doesn't, then the cpuThingy instance must be explicitly initialized in the Cpu.cpp file, in the constructor initialization sequence:

Cpu::Cpu() : cpuThingy(whatever arguments it needs)
{
}

Hello PaulS, thanks for your interest. In response to your answer:

About first try:

#include "utilities/CpuOutput.h"
Cpu::Cpu(): outputObject(){}

Did you define a destructor? Did you implement the destructor?

Yes I did for CpuOutut files, definition in .h (inside 'public:' members, after constructor definition): ~CpuOutput();
and the implementation in .cpp, at the end of file: CpuOutput::~CpuOutput(){}
The same things in .h and .cpp files of Cpu class, for respective destructor (~Cpu(); etc.)

About second try:

#include "utilities/CpuOutput.h"
Cpu::Cpu(){  cpuObject();  }

That is NOT how to create an instance of the class. You NEVER call the constructor directly.

I understood, so I will never try it again

The gist:
I tried with your example, but I still have the same error:

undefined reference to `CpuOutput::~CpuOutput()'
undefined reference to `CpuOutput::CpuOutput()'

So as you requested me, here are the Cpu .h and Cpu .cpp files:
note: Cpu class name = Cpu1284. CpuOutput class name = Cpu1284ExtendedInput.

Cpu1284.h

#if(ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#endif

#include "utilities/Cpu1284ExtendedInput.h"
#include <inttypes.h>

#ifndef Cpu1284_h
#define Cpu1284_h

class Cpu1284{
	public:	
		Cpu1284();

		~Cpu1284();
	private:
		// Analog/digital Input pins sector1
		uint8_t d18; 	// control0   	extendedInput library
		uint8_t d19;	// control1   	"
		uint8_t d20;	// control2   	"
		uint8_t d21;	// control3   	"
		uint8_t a0;	// analogData 	"
		// Digital Input pins sector2 (both sectors share d18-d21 pins)
		uint8_t a1;	// digitalData	"
		// Digital Output pins sector3
		uint8_t d22;	// latchPin	extendedOutput library (maybe clockPin)
		uint8_t d23;	// clockPin	extendedOutput library (maybe latchPin)
		uint8_t d0;	// dataPin	extendedOutput library
		// Lcd pins (digital outputs)
		uint8_t d4;
		uint8_t d5;
		uint8_t d6;
		uint8_t d7;
		uint8_t a2;
		uint8_t a3;
		uint8_t a4;
		uint8_t a5;
		uint8_t a6;
		// Motor1 pins (digital outputs)
		uint8_t d3;
		uint8_t d12;
		// Motor2 pins (digital outputs)
		uint8_t d13;
		uint8_t d14;
		// Encoder pins (digital inputs)
		uint8_t d1;
		uint8_t d2;
		// Interruptor pins
		uint8_t d10;
		// rs485 pins
		uint8_t rx0;
		uint8_t tx0;
		uint8_t a7;


		uint8_t lcdEnabled;
		uint8_t encoderEnabled;
		uint8_t motorEnabled;
		uint8_t digitalInputsSector1Enabled;

		Cpu1284ExtendedInput extendedInput;


		// Internal functions
		void enableFeatures();
		void enableLCD();
		void enableEncoder();
		void enableMotor();
		void enableMuxPins();
};

#endif

Cpu1284.cpp

#if(ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#endif

#include "Cpu1284.h"
#include "utilities/Cpu1284ExtendedInput.h"
#include <inttypes.h>


// CONSTRUCTOR
Cpu1284::Cpu1284() : extendedInput(){
	lcdEnabled = 0;
	encoderEnabled = 0;
	motorEnabled = 0;
	digitalInputsSector1Enabled = 0;

	enableMuxPins();
}

// INTERNAL FUNCTIONS
void Cpu1284::enableFeatures(){
	if(lcdEnabled != 0){
		enableLCD();
	}
	if(encoderEnabled != 0){
		enableEncoder();
	}
	if(motorEnabled != 0){
		enableMotor();
	}
	enableMuxPins();
}

void Cpu1284::enableLCD(){
	/* lcdEnabled = 1: 20x2 size, 6 pins needed
	   	      = 2: 20x4 size, 7 pins needed
		      = 3: 40x2 size, 7 pins needed
		      = 4: 40x4 size, 8 pins needed	
	 */
	d4 = 4;
	d5 = 5;
	d6 = 6;
	d7 = 7;
	a2 = 26;
	a3 = 27;
	pinMode(d4, OUTPUT);
	pinMode(d5, OUTPUT);
	pinMode(d6, OUTPUT);
	pinMode(d7, OUTPUT);
	pinMode(a2, OUTPUT);
	pinMode(a3, OUTPUT);
	if(lcdEnabled > 1){
		a4 = 28;
		pinMode(a4, OUTPUT);
		if(lcdEnabled > 3){
			a5 = 29;
			pinMode(a5, OUTPUT);
		}
	}
}

void Cpu1284::enableEncoder(){
	d1 = 1;
	d2 = 2;
	pinMode(d1, INPUT);
	pinMode(d2, INPUT);
}

void Cpu1284::enableMotor(){
	d3 = 3;
	d12 = 12;
	pinMode(d3, OUTPUT);
	pinMode(d12, OUTPUT);
	if(motorEnabled == 2){
		d13 = 13;
 		d14 = 14;
		pinMode(d13, OUTPUT);
		pinMode(d14, OUTPUT);
	}
}

void Cpu1284::enableMuxPins(){
	// Activate analog/ditigal Input Mux pins from Sector 1
	d18 = 18;
	d19 = 19;
	d20 = 20;
	d21 = 21;
	a0 = 24;
	pinMode(d18, INPUT);
	pinMode(d19, INPUT);
	pinMode(d20, INPUT);
	pinMode(d21, INPUT);
	pinMode(a0, INPUT);

	// Activate digital Input Mux pins from Sector 2
	a1 = 25;
	pinMode(a1, INPUT);
	// Activate digital Output Mux pins from Sector 3
	d22 = 22;
	d23 = 23;
	d0 = 0;
	pinMode(d22, OUTPUT);
	pinMode(d23, OUTPUT);
	pinMode(d0, OUTPUT);
}

Cpu1284::~Cpu1284(){
}

Cpu1284ExtendedInput Files (runs and compiles ok, tested)

Cpu1284ExtendedInput.h (located at /Cpu1284/utilities)

#include <inttypes.h>
#ifndef Cpu1284ExtendedInput_h
#define Cpu1284ExtendedInput_h

class Cpu1284ExtendedInput{
	public:
		// Constructor
		Cpu1284ExtendedInput();
		// Destructor
		~Cpu1284ExtendedInput();
		void setParameters(uint8_t Control0, uint8_t Control1, uint8_t Control2, uint8_t Control3, uint8_t digitalData, uint8_t analogData);
		void inputsRead(uint8_t *muxDigital, int *muxAnalog);
	private:
		uint8_t c0;
		uint8_t c1;
		uint8_t c2;
		uint8_t c3;
		uint8_t dD;
		uint8_t aD;
};
#endif

Cpu1284ExtendedInput.cpp (located at /Cpu1284/utilities)

#include "Cpu1284ExtendedInput.h"
#if(ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
#include <stdlib.h>
#include <inttypes.h>

// Constructor
Cpu1284ExtendedInput::Cpu1284ExtendedInput(){
}

void Cpu1284ExtendedInput::setParameters(uint8_t Control0, uint8_t Control1, uint8_t Control2, uint8_t Control3, uint8_t digitalData, uint8_t analogData){
	c0 = Control0;
	c1 = Control1;
	c2 = Control2;
	c3 = Control3;

	dD = digitalData;
	aD = analogData;

	digitalWrite(dD, HIGH);
}

void Cpu1284ExtendedInput::inputsRead(uint8_t *muxDigital, int *muxAnalog){
	//This for loop is used to scroll through and store the 16 inputs on the FIRST multiplexer
  	for (uint8_t i=0; i<16; i++){

    		//The following 4 commands set the correct logic for the control pins to select the desired input
    		//See the Arduino Bitwise AND Reference: http://www.arduino.cc/en/Reference/BitwiseAnd
    		//See the Aruino Bitshift Reference: http://www.arduino.cc/en/Reference/Bitshift
    		digitalWrite(c0, (i&15)>>3);
    		digitalWrite(c1, (i&7)>>2); 
    		digitalWrite(c2, (i&3)>>1); 
    		digitalWrite(c3, (i&1));  

    		//Read and store the input
    		//Since internal pullup is on, the pin goes low on changing, so the value needs to be flipped from 0 to 1 (!)
    		muxDigital[i] = !digitalRead(dD);
    		muxAnalog[i] = analogRead(aD);
  	}
}

// Deconstructor
Cpu1284ExtendedInput::~Cpu1284ExtendedInput(){
}

I hope you can help me. Thanks again

Where is your sketch?

My sketchbook is in my user ubuntu folder I think, but I don't remenber exactly right now because I'm at my house now and I don't have the working pc here

Anyway that's not a problem, I have other programs running ok, and they are heavy programs

Thanks

[Edit] Try if you want, to put this libraries in your libraries folder (placing Cpu1284ExtendedInput files in /Cpu1284/utilities/), and simply create an .ino program with the #include <cpu1284.h>, empty setup() and empty loop(). You should have the same error as I have?

In case you have to know where skecthbook folder exactly is, to think of an answer

sketchbook folder: /home/myuserFolder/sketchbook (linux)

Thanks

I pasted the code you showed into 4 tabs in Notepad++, and then saved the tabs in the appropriate places. I created a sketch, and included Cpu1284.h, NOT cpu1284.h (which doesn't exist).

I got one error message, concerning a line I apparently mangled when I put the curly braces where they belong (on separate lines, notjammedtightupagainsthefunction.

After I fixed that, I got:

Binary sketch size: 466 bytes (of a 30,720 byte maximum)

Apparently, just an empty sketch is NOT enough to illustrate the problem. So, I'll ask again. What does your sketch look like?

I added

Cpu1238 whatever;

to the sketch. Then, I got the unresolved references messages.

I moved Cpu1284ExtendedInput.cpp/.h from utilities to Cpu1284, and removed

#include "utilities/Cpu1284ExtendedInput.h"

from Cpu1284.cpp and I removed utilities from the include statement in Cpu1284.h. Then, the sketch and libraries compile and link with no errors.

Whether the class actually does anything is for you to test.

My god, this was the solution.. I think I would not be able to fix it

Effectively, move Input files from Cpu1284/utilities/.cpp .h to Cpu1284/.cpp .h in the same place as the Cpu1284 files, and change the #include "utilities/Cpu1284ExtendedInput.cpp .h" line by #include "Cpu1284ExtendedInput.cpp .h" was the solution.

By the moment program compiles. Will see what happens when I'll try to use the object definition in .cpp and execute one of his methods

Very Thankful to all of you people who tried to help me, specially to PaulS and WizenedEE