Resolving a linker error: undefined reference to s

2019-01-28 06:41发布

问题:

My code is Arduinoish. I turned on verbose compiling so I could verify that all the .o files are indeed getting passed to the linker correctly, and they are (linker command below). This leads me to believe that it is some sort of syntax error.

Googling for the error "undefined reference to in function" produces a lot of results with answers like "add foo.o to your linker command like so", etc.

I hope the solution is as simple as a missing dot or -> somewhere.

I'm getting this series of errors in one file, from the linker:

SerialServoControl.cpp.o: In function `SerialServoControl::send(int, int)':
SerialServoControl.cpp:31: undefined reference to `SerialServoControl::_serial'
SerialServoControl.cpp:31: undefined reference to `SerialServoControl::_serial'
SerialServoControl.cpp.o: In function `SerialServoControl::init(char, char)':
SerialServoControl.cpp:9: undefined reference to `SerialServoControl::_tx'
SerialServoControl.cpp:10: undefined reference to `SerialServoControl::_rx'

The .h file:

#ifndef SERIALSERVOCONTROL_H
#define SERIALSERVOCONTROL_H

#include "NewSoftSerial.h"

class SerialServoControl {
    public:
          //                             rx, tx
          static NewSoftSerial _serial;//(9, 8);

          int _servo_id;
          static char _tx;
          static char _rx;

          static void init(char tx, char rx);
          static void send(int servo_id, int angle);
          void setup(int servo_id);
          void set(int spot);
};

#endif

and the .cpp file:

#ifndef SERIALSERVOCONTROL_CPP
#define SERIALSERVOCONTROL_CPP

#include "WProgram.h"
#include "SerialServoControl.h"

//static
void SerialServoControl::init(char tx, char rx){
    _tx = tx;
    _rx = rx;
    _serial = NewSoftSerial(rx, tx);
    _serial.begin(9600);
}

//static
void SerialServoControl::send(int servo_id, int angle){
    unsigned char buff[6];

    int temp     = angle & 0x1f80;
    char pos_hi  = temp >> 7;
    char pos_low = angle & 0x7f;

    buff[0] = 0x80;        // start byte
    buff[1] = 0x01;        // device id
    buff[2] = 0x04;        // command number
    buff[3] = servo_id;       // servo number
    buff[4] = pos_hi;      // data1
    buff[5] = pos_low;     // data2

    for(int i=0; i<6; i++){
        _serial.print(buff[i], BYTE);

    }
}


void SerialServoControl::setup(int servo_id){
    _servo_id = servo_id;
}

void SerialServoControl::set(int angle){
    SerialServoControl::send(_servo_id, angle);
}

#endif

The linker command (I've removed the explicit temporary directory paths that the IDE generates for clarity and broken it out to multiple lines. The actual command is explicit as to the location of all these files):

  avr-gcc -Os -Wl,--gc-sections -mmcu=atmega328p \
  -o Wheel_Chair_Joystick_Control.cpp.elf \
  SerialServoControl.cpp.o \
  Wheel_Chair_Joystick_Control.cpp.o \
  WheelChairMotor.cpp.o \
  NewSoftSerial.cpp.o \
  core.a \
  -Lbuild277668752723095706.tmp \
  -lm

All of these files (SerialServoControl, Wheel_Chair_Joystick, NewSoftSerial, WheelChairMotor) exist in the Arduino sketch directory. Core.a is the compiled AVR library.

回答1:

You have to define your class statics in a source file some where. Putting them in the class just declares that they are there, but something still needs to define them.

Inside your .cpp file your can do so like this:

NewSoftSerial SerialServoControl::_serial(9, 8);
char SerialServoControl::_tx = 0;
char SerialServoControl::_rx = 0;

Put appropriate initial values; I just assumed the comment was for the constructor.



回答2:

You need to create memory and initialize your static variables.

In your CPP file add the following:

NewSoftSerial SerialServoControl::_serial(9, 8);
char SerialServoControl::_tx = 0;
char SerialServoControl::_rx = 0;


回答3:

Because the value _serial is static, it exists when an object isn't instantiated. This means that you must declare it in the code as

NewSoftSerial SerialServoControl::_serial(9, 8);
char SerialServoControl::_tx = 0;
char SerialServoControl::_rx = 0;

which has already been suggested.

If you then want to change it in the init function, you simply have to change your _serial = ... line to SerialServoControl::_serial = NewSoftSerial(tx, rx). Of course, this means you'll have to define a relevant constructor for the NewSoftSerial class.

Hope this helps.



回答4:

I know this is somewhat dead, but in my case I forgot to define the methods I was referencing, imagine that.......

Yes they were DECLARED, but when I checked my .cpp file, there was no definition for them, so this time the error was literal.