Using a library inside of another library errors

Hello, I am making a library to help me interface with a proprietary inverter, we are going to communicate with it over CAN. I would like to use the MCP2515 library inside of the inverter library. When creating an MCP2515 object, you have to give it the pin number that its connected to. I would like to just create an inverter object, and give it to the mcp2515 library. When i do this is what i do not know. here are some snippets of my codes:

PD400.h

#ifndef PD400_h
#define PD400_h
#include "Arduino.h"
#include <SPI.h>
#include <mcp2515.h>


class PD400
{
  public:
    PD400(int pin);
    void Begin();
    void dot();
    void dash();
  private:
    int _pin;
    MCP2515 mcp(10);
    

    // String[] recieveString;
    struct can_frame canMsg;

};

#endif

PD400.cpp

#include "Arduino.h"
#include "PD400.h"
#include <SPI.h>
#include <mcp2515.h>
MCP2515 mcp;
PD400::PD400(int pin)
{

  _pin = pin;
}



void PD400::Begin(){
  SPI.begin();
  mcp.reset();
   mcp.setBitrate(CAN_500KBPS, MCP_8MHZ);
   mcp.setNormalMode();
}

and my actual .ino file

#include <mcp2515.h>

//PD400 pd400(10);
void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

the error I get is

In file included from C:\Users\Eric\Documents\Formula Electric\PD400Library\TestingLibrary\TestingLibrary.ino:1:0:

C:\Users\Eric\Documents\Arduino\libraries\PD400/PD400.h:17:17: error: expected identifier before numeric constant

     MCP2515 mcp(10);

                 ^~

C:\Users\Eric\Documents\Arduino\libraries\PD400/PD400.h:17:17: error: expected ',' or '...' before numeric constant

exit status 1
Error compiling for board Arduino Uno.

Any help is appreciated!

I think that you cannot construct the object in the class' declarations like that. I struggled so much with this at some point and I couldn't understand the answers I found either.

class Thing{
   int m=0;
}

I remember at some point I also thought I could do that, because I thought that it was equivalent to the "global" scope found on the main .ino file. It is not

A good place to construct objects contained in a class is in this part of the constructor where you assign parameters to object's properties. I don't know the name of that, but I can show:

class Class1{
    public:
    int m=0;
    Class1(int _m):m(_m){}
};

class Class2{
    public:
    Class1 ownedObject;
    Class2():ownedObject(10){
    }
};

Another thing you can approach this is using a reference. The object does not own the object but expects to get a reference to it, so that it can use it

class Class1{
    public:
    int m=0;
    Class1(int _m):m(_m){}
};

class Class2{
    public:
    Class1 & sharedObject;
    Class2(Class1 & _sharedObject):sharedObject(_sharedObject){
    }
};

Class1 nolol = Class1(33);
Class2 lol = Class2(nolol);

The line is inside a class declaration so the compiler thinks you are declaring a variable or function. It sees the type MCP2515 and the name 'mcp' and then sees an '(' which means 'mcp' is a function. After that should be the argument list but instead of a type, it gets an integer.

   private:
    int _pin;
    MCP2515 mcp(10);

// Change that to:

   private:
    int _pin;
    MCP2515 mcp;

To pass constructor arguments to a member variable you have to do it in the constructor:

PD400::PD400(int pin) : mcp(10)
{
  _pin = pin;
}

johnwasser:
// Change that to:

   private:

int _pin;
    MCP2515 mcp;




To pass constructor arguments to a member variable you have to do it in the constructor:


PD400::PD400(int pin) : mcp(10)
{
  _pin = pin;
}

I did what john suggested, now I am getting a different error:

C:\Users\Eric\Documents\Arduino\libraries\PD400\PD400.cpp:5:9: error: no matching function for call to 'MCP2515::MCP2515()'

 MCP2515 mcp;

         ^~~

In file included from C:\Users\Eric\Documents\Arduino\libraries\PD400\PD400.h:5:0,

                 from C:\Users\Eric\Documents\Arduino\libraries\PD400\PD400.cpp:2:

C:\Users\Eric\Documents\Arduino\libraries\arduino-mcp2515-master/mcp2515.h:459:9: note: candidate: MCP2515::MCP2515(uint8_t)

         MCP2515(const uint8_t _CS);

         ^~~~~~~

C:\Users\Eric\Documents\Arduino\libraries\arduino-mcp2515-master/mcp2515.h:459:9: note:   candidate expects 1 argument, 0 provided

C:\Users\Eric\Documents\Arduino\libraries\arduino-mcp2515-master/mcp2515.h:205:7: note: candidate: constexpr MCP2515::MCP2515(const MCP2515&)

 class MCP2515

       ^~~~~~~

C:\Users\Eric\Documents\Arduino\libraries\arduino-mcp2515-master/mcp2515.h:205:7: note:   candidate expects 1 argument, 0 provided

C:\Users\Eric\Documents\Arduino\libraries\arduino-mcp2515-master/mcp2515.h:205:7: note: candidate: constexpr MCP2515::MCP2515(MCP2515&&)

C:\Users\Eric\Documents\Arduino\libraries\arduino-mcp2515-master/mcp2515.h:205:7: note:   candidate expects 1 argument, 0 provided

exit status 1
Error compiling for board Arduino Uno.

Darn. The member object has no default constructor (constructor with no arguments). I've hit the limit of my knowledge of weird member object initialization. Maybe you have to make 'mcp' a reference?

   private:
    int _pin;
    MCP2515 &mcp;

same error :frowning:

Use @johnwasser's suggestion in Reply #2 and get rid of this line in your .cpp file:
MCP2515 mcp;

Read about initializer lists here: When do we use Initializer List in C++? - GeeksforGeeks. This is Case #3 in that article.

If you still get an error, post your COMPLETE new code and the error message.

It's best to post any code as an MRE. Read how to do that here: How to create a Minimal, Reproducible Example - Help Center - Stack Overflow

It compiles!

in my .h file I ended up going with

private:
    int _pin;
    MCP2515 mcp;

in my .cpp file I ended up going with

PD400::PD400(int pin) : mcp(pin){

  _pin = pin;
}

thanks for all of your help!

erit1566:
in my .cpp file I ended up going with

PD400::PD400(int pin) : mcp(pin){

_pin = pin;
}

Why not this?

PD400::PD400(int pin) : mcp(pin), _pin(pin) {
}

Declare it like this in your class…

private:
MCP2515* mcp; // ← Ponter to this kind of thing.

And in your cinstructor… Fire it up like this…

PD400::PD400(int pin) {

mcp = new MCP2515(pin);
}

And to access it, just use → instead of .

-jim lee

jimLee:
Declare it like this in your class…

private:
MCP2515* mcp; // ← Ponter to this kind of thing.

And in your cinstructor… Fire it up like this…

PD400::PD400(int pin) {

mcp = new MCP2515(pin);
}

And to access it, just use → instead of .

-jim lee

Why do it dynamically? Given OP’s requirements, there’s absolutely no advantage to this over just having a private MCP2515 data member per Reply #'s 2 & 8.

Why beat me up? I've hit this issue 100 times. That's the way I 'd do it.

-jim lee

erit1566:
It compiles!

private:

int _pin;
   MCP2515 mcp;





PD400::PD400(int pin) : mcp(pin) {
 _pin = pin;
}

That is weird. I wonder why it refused to take what I suggested:

   private:
    int _pin;
    MCP2515 mcp;
PD400::PD400(int pin) : mcp(10)
{
  _pin = pin;
}

They are identical except '10' is a constant and 'pin' is an argument.

johnwasser:
That is weird. I wonder why it refused to take what I suggested:

   private:

int _pin;
   MCP2515 mcp;





PD400::PD400(int pin) : mcp(10)
{
 _pin = pin;
}




They are identical except '10' is a constant and 'pin' is an argument.

Your suggestion was fine. Trouble was (per my post in Reply #6), OP had an extraneous instantiation of an MCP2515 object in the .cpp file that was messing things up. Once that is removed, either way will work. However, for flexibility, I prefer not to hard-code things like pin assignments in the class declaration. Better to have the code that instantiates the object supply them.