Initialize a class so all header files can use it?

21 Oct 2012

I'm sorry the topic should of said "Initialize a class once inside a header so all cpp files can use it?"

Hi all, Is it possible to initialize(or is that called declare?) a class inside one header file so all the other .cpp files can use the initialized class? For example, I am creating a library to use along side of MODSERIAL. My .cpp files contain functions that use the MODSERIAL library. The .cpp code produces this error: `"variable "pc" has already been defined" in file "/msExtensions.cpp", Line: 19, Col: 1`

Inside my msExtensions.cpp file I have:

// FILE: msExtensions.cpp
/*
File: msExtensions.cpp
 
Contains code to utilise MODSERIAL Extensions:
 
Constructor
*/

#include "ConfigFile.h" 
#include "msExtensions.h"
#include "cfExtensions.h"
#include "MODSERIAL.h"


// Initialize MODSERIAL
MODSERIAL pc(USBTX, USBRX);
MODSERIAL sensor(p28, p27);  // tx, rx

pc.baud(38400);
sensor.baud(38400);
 
pc.attach(&pcRecvInterrupt, MODSERIAL::RxAutoDetect);
pc.autoDetectChar('\r');

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//================================
// ConfigFile Extentions Constructor
//================================
msExtensions: msExtensions()
{
       

} // End of ConfigFile Extensions Constructor


/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//================================
// Ping the base station
//================================
void msExtensions::pingBaseStation() {
    printf("{\"sbPing\": \"%s\"}\r\n", sbNameValue);
} // End of pingBaseStation function


/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//================================
// MODSERIAL RX Interrupt and move
//================================
void msExtensions::pcRecvInterrupt(MODSERIAL_IRQ_INFO *q) {
    MODSERIAL *serial = q->serial;
    serial->move(pcResponseValue, 512);
    serial->rxBufferFlush();
} // End of pcRecvInterrupt function

msExtensions.h file code:

/*
File: msExtensions.h
 
Header file for msExtensions Library.
*/
 
#ifndef MS_Extns_H
#define MS_Extns_H
 
#include "mbed.h"
 
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//==================================
// Definitions
//==================================
//#define CF_FILE_LOCATION  "local/settings.cf"     // File location locatl/settings.cf
 
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//==================================
// msExtension Class
//==================================
class msExtensions
{
public:
//---------------------------
// Function Prototypes
//---------------------------
        msExtensions();                         // Constructor, Initialization tasks
        
        void pingBaseStation();

        
//---------------------------
// Variables
//---------------------------
        volatile bool pcResponse;

        char pcResponseValue[512];
        
//---------------------------
// Devices
//--------------------------- 
                       
};
    
#endif

OR maybe a better question that I should of asked is how do I declare the MODSERIAL library inside my class? Also, is it possible to declare MODSERIAL once so the rest of my future classes can us it?

21 Oct 2012

The problem is now you don't declare the pc MODSERIAL object inside your class, but outside the class (it isn't in the constructor or a function), so it clashes with the object with the same name in your main.cpp probably. You have to create the pc variable inside your header file to make sure it is valid only for that class. You can do that in several ways, this is for example how I generally do it: http://mbed.org/users/Sissors/code/MMA7660/docs/tip/ (Only then for I2C, but you should be able to do the same with modserial, in the header file it should be defined somewhere in the bottom, and then in the constructor it gets it arguments).

Regarding your last question: yes you can do that. You need to do something like the following:

In your main:

#include "mbed.h"
#include "Everythingelseyouwanttouse.h"

MODSERIAL pc(USBTX, USBRX);
YourClass blabla(&pc);  //Now we give a pointer to the modserial object in the constructor. 
                        //You can also use a function to do it, but now we are sure we always got a MODSERIAL object

Your your header file:

#ifdef stuff

#include "mbed.h"
#include "MODSERIAL.h"

class YourClass
{
public:
YourClass(MODSERIAL *pc);   //Request pointer to MODSERIAL object



private:
MODSERIAL *_pc;             //pointer to MODSERIAL object
}

Then in your cpp file:

YourClass::YourClass(MODSERIAL *pc) {
  _pc = pc;                 //Set your internal MODSERIAL pointer to the one we just got
}

int YourClass:YourFunction( void ) {
  _pc -> baud(921600);      //Now we can for example change the baudrate, this changes the baudrate for everything that uses the MODSERIAL declared in your main
                            //Because we now got a pointer to a MODSERIAL object instead of an actual object we need to use the '->' instead of the '.'
  
   //Equivalent to:
   (*_pc).baud(921600); 
}

I haven't actually ever used this myself, so there could be flaws in it, but afaik in principle it should work like this.

23 Oct 2012

Hi Erik. Thank You! I read your code example and searched google for more literature about C++ classes. Now I think I grasp the beginning stages of writing C++ classes; however, I am stuck on accessing variables and methods from another class. For Example, I could have class1 and class2 in their own .h and .cpp files. Class1 has a variable declared as char *sbNameKey; and a method called methodOne. Class2 requires access to Class1 sbNameKey variable and methodOne method. Should I friend class1 in class2 or should I create an oject of class1 to access the sbNameKey variable and the methodOne method? I'm a little confused about which route to take. At some point I would like to attach a function to My realworld example: <<code>> _pingTick.attach(this, &msExtensions::pingBaseStation, 10); <</code>>df

As that code stands, I receive error: "no instance of overloaded function "mbed::Terial::attach" matches the argument list" My guess is that I have not declared an instance of Ticker? I did however, place Ticker _pingTick; in my private section of my classes .h file.

Maybe you can shed some light?

23 Oct 2012

Hey,

I don't know much either about friending classes and stuff like that. What you can always do is pass around data in your main function, or to declare in your example the class 1 object inside your class 2.

Regarding your ticker problem that should work, but now we are also kinda arriving at the limit of my knowledge, I am not all that into C++ either ;)

23 Oct 2012

Thanks again for your help. I will linger around google to learn more.

Erik - wrote:

Hey,

I don't know much either about friending classes and stuff like that. What you can always do is pass around data in your main function, or to declare in your example the class 1 object inside your class 2.

Regarding your ticker problem that should work, but now we are also kinda arriving at the limit of my knowledge, I am not all that into C++ either ;)

23 Oct 2012

d 0773d wrote:

I am stuck on accessing variables and methods from another class. For Example, I could have class1 and class2 in their own .h and .cpp files. Class1 has a variable declared as char *sbNameKey; and a method called methodOne. Class2 requires access to Class1 sbNameKey variable and methodOne method. Should I friend class1 in class2 or should I create an oject of class1 to access the sbNameKey variable and the methodOne method?

Depends on what you are trying to do, the following may be what you need if there is only one object of class1:

  • declare Class1 (cpp and h).
  • declare Class2, include Class1.h in Class2.h
    • instantiate an object of Class1 as private object in Class2.
    • access the now local Class1 variables from inside your Class2 methods and/or call Class1 methods.

In case you have multiple objects of type Class1 that need to be accessed by multiple other classes, one of which is Class2, then you need to provide Class2 with the pointers to these objects before using the specific class1 variable or method.

  • declare Class1 (cpp and h).
    • instantiate object(s) of Class1
  • declare Class2, include Class1.h in Class2.h
    • declare a pointer to an object of Class1 as private in Class2.
    • instantiate an object of Class2
    • call a Class2 method to init the private pointer to a specific Class1 instance (you could also provide that pointer as part of the Class2 constructor)
    • access the referenced Class1 variable from inside your Class2 methods and/or call Class1 methods.

I used something similar in the example code below: declare an object 'i2c''and pass that as parameter to several other objects (PCF8574_xxx) as part of their constructor. These new objects are in turn parameters to yet another object (HDSP253X_Display):

//I2C Bus
I2C i2c(D_SDA, D_SCL);
 
// Bus Interface Hardware definitions
PCF8574_DataBus    databus = PCF8574_DataBus(i2c, D_I2C_DATA_BUS);  //Copy constructors..
PCF8574_AddressBus addressbus = PCF8574_AddressBus(i2c, D_I2C_ADDR_BUS);
PCF8574_EnableBus  enablebus = PCF8574_EnableBus(i2c, D_I2C_ENA_BUS);
MBED_ControlBus  controlbus = MBED_ControlBus(D_WR, D_RD, D_DTR, D_CDBUF, D_CDINT);
 
// Display Hardware definitions
HDSP253X_Display LED_display = HDSP253X_Display(databus, addressbus, enablebus, controlbus);

see http://mbed.org/users/wim/code/mbed_bus/

and http://mbed.org/users/wim/notebook/mbed-addressbus-databus-and-controlbus/#