Pages: [1] 2   Go Down
Author Topic: [solved] how to call a class from my own library, inside another own library  (Read 1212 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
« Last Edit: March 11, 2013, 09:30:25 am by Bonetky » Logged

Rome, Italy
Offline Offline
Sr. Member
****
Karma: 20
Posts: 442
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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)
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Rome, Italy
Offline Offline
Sr. Member
****
Karma: 20
Posts: 442
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is how it should be, where "arduino" is the sketchbook directory
Code:
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
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Code:
'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:
Code:
undefined reference to `CpuOutput::~CpuOutput()'
undefined reference to `CpuOutput::CpuOutput()'
Seems like is waiting for the constructor?

If I write
Code:
'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:
Code:
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
« Last Edit: March 01, 2013, 06:14:31 am by Bonetky » Logged

North Queensland, Australia
Offline Offline
Edison Member
*
Karma: 74
Posts: 2225
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
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.

Code:
CpuOutput outputObject();

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

Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
Code:
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;
};
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

At Cpu.h
Code:
#include "utilities/CpuOutput.h"

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

At Cpu.cpp

If I write this:
Code:
#include "utilities/CpuOutput.h"

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

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

Alternatively, if I write this at Cpu.cpp:
Code:
#include "utilities/CpuOutput.h"

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

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


Otherwise, If I don't modify Cpu.cpp at all, and I write this on Cpu.h
Code:
#include "utilities/CpuOutput.h"

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

Obviously, I have the error:
Code:
expected `{' at end of input


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

Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 642
Posts: 50423
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
If I write this:
Code:
#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?

Quote
Alternatively, if I write this at Cpu.cpp:
Code:
#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.

Quote
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
Code:
   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:
Code:
Cpu::Cpu() : cpuThingy(whatever arguments it needs)
{
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

About first try:
Code:
#include "utilities/CpuOutput.h"
Cpu::Cpu(): outputObject(){}
Quote
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):
Code:
~CpuOutput();
and the implementation in .cpp, at the end of file:
Code:
CpuOutput::~CpuOutput(){}
The same things in .h and .cpp files of Cpu class, for respective destructor (~Cpu(); etc.)

About second try:
Code:
#include "utilities/CpuOutput.h"
Cpu::Cpu(){  cpuObject();  }
Quote
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:
Code:
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
Code:
#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
Code:
#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)
Code:
#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)
Code:
#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
« Last Edit: March 05, 2013, 04:54:56 am by Bonetky » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 642
Posts: 50423
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Where is your sketch?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
« Last Edit: March 05, 2013, 11:58:54 am by Bonetky » Logged

Pages: [1] 2   Go Up
Jump to: