How does this compile in Arduino IDE? - c++

I have noticed the following code, which is obviously invalid C++, compiles in Arduino IDE (using AVR-GCC):
// The program compiles even when the following
// line is commented.
// void someRandomFunction();
void setup() {
// put your setup code here, to run once:
someRandomFunction();
}
void loop() {
// put your main code here, to run repeatedly:
}
void someRandomFunction() {
}
What is going on here? C++ requires functions to be declared before they are used. When the compiler comes to the line someRandomFunction() in the setup() function, how does it know it will be declared?

This is what we call Forward declaration and in C++ it only requires you to declare the prototype of the function before attempting to use it, instead of defining the whole function.:
Taking as example the following two pieces of code:
CODE A:
#include <Arduino.h>
void setup(){}
void AA(){
// any code here
}
void loop(){
AA();
}
CODE B:
#include <Arduino.h>
void setup(){}
void loop(){
BB();
}
void BB(){
// any code here
}
Strictly speaking C requires that functions be forward declared for the compiler to compile and link them. So in CODE A we do not have declared the function but it defined, which makes it legal for proper C code. But the CODE B has the function definition after the loop, which would be illegal for plain C. A solution would be the following one:
#include <Arduino.h>
void BB();
void setup(){}
void loop(){
BB();
}
void BB(){
// any code here
}
This, however, to fit the Arduino script format of having a void setup() following from a void loop(), required Arduino to include a script on its IDE that automatically looks for functions and generate prototypes up top for you so you do not need to worry about it. So despite being written in C++, you will NOT see Arduino sketches using Forward declaration often in their sketches, as it works out fine and it is often easier to read having first setup() and loop().

Your file is .ino not .cpp. .ino is 'Arduino language'.
The main ino file with additional ino files are processed by the Arduino builder to C++ source and only then processed as C++ (preprocessor, compilation).

Related

Undefined reference to `TESTCLASS::TESTCLASS()'

Although I read a few google-results for that error I can't find my problem for this error, not even while trying to reduce everything to its very basic content.
That's my testclass.h:
class TESTCLASS {
public:
TESTCLASS();
};
int x; // I added this for testing if the file is included from my main code file
x=10; // It is and throws this error: testclass.h:8:1: error: 'x' does not name a type, which I don't understand neither, but it't not the main problem here
testclass.cpp:
#include "testclass.h"
TESTCLASS::TESTCLASS() {
// do some stuff
}
and here's my main code file:
#include "lib/testclass.h"
TESTCLASS test;
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}
This throws the error
/var/folders/b5/qc8dstcn02v_hyvgxsq4w9vr0000gq/T//ccQOziAu.ltrans0.ltrans.o: In function `_GLOBAL__sub_I_test':
/Volumes/Daten/stefanherzog/Documents/Nextcloud/Programmierung/Arduino/200515_growboxLibrary_test/200515_growboxLibrary_test.ino:3: undefined reference to `TESTCLASS::TESTCLASS()'
collect2: error: ld returned 1 exit status
exit status 1
So even this is very basic I can't see the problem! I'm using an avr-g++ compiler within my Arduino IDE (v1.8.12).
Can someone please explain me what I'm doing wrong?
it looks like you don't send testclass.cpp to your compiler. If so, your problem does'nt come from your code but your compiling command line.
Using gcc you should have something like :
g++ main.cpp lib/testclass.cpp -o testclass
I don't know the compilation process for arduino but i hope it will helps you finding the solution.
Easiest put testclass.cpp into the same folder as your .ino file. It should show up as a separate tab.
Put testclass.h there as well. and remove the lib subfolder.
And remove the int x=10; definition from the .h file. If both units are including testclass.h, that should end up in a duplicate error.
BTW: an assignment x=10; outside a function is nonsense anyway.
When using subdirectories with the Arduino IDE the subdirectory needs to be named as utility. That's actually it!
Having this structure for example (in ../Arduino/libraries/):
./testclass
./testclass/testclass.h
./testclass/testclass.cpp
./testclass/sub
./testclass/sub/sub.h
./testclass/sub/sub.cpp
testclass.h:
#ifndef __TESTCLASS_H__
#define __TESTCLASS_H__
#include "utility/sub.h"
class TESTCLASS {
public:
TESTCLASS();
};
#endif
testclass.cpp:
#include "testclass.h"
TESTCLASS::TESTCLASS() {
// do some stuff
}
sub.h:
class SUBCLASS {
public:
SUBCLASS();
};
sub.cpp:
#include "sub.h"
SUBCLASS::SUBCLASS() {
// do some stuff
}
You can simply include the "main" testclass.h in your project and instantiate the class and even the subclass:
#include <testclass.h>
TESTCLASS test;
SUBCLASS sub;
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}

Passing instance of a class to function in c++

I am programming in arduino land. using a library AccelStepper.h with a class AccelStepper
I created an instance as follows:
AccelStepper panStepper(AccelStepper::DRIVER, PAN_STEP_PIN, PAN_DIR_PIN);
AccelStepper tiltStepper(AccelStepper::DRIVER, TILT_STEP_PIN, TILT_DIR_PIN);
AccelStepper dollyStepper(AccelStepper::DRIVER, DOLLY_STEP_PIN, DOLLY_DIR_PIN);
I want to be able to pass a reference to one of the instances and be able to change the parameters of that instance.
I am using the following to create a function to work on one of the instances as follows:
void CalibrateAxis(AccelStepper& stepper, int min_pin, int max_pin) {
this is screwing up the arduino compiler, causing it to put forward declarations for this function and others in the middle of a pragma in the main ino file as follows:
// RemoteXY configurate
#pragma pack(push, 1)
//
//
void CalibrateAxis(AccelStepper& stepper, int min_pin, int max_pin);
void CalibrateAll();
void StepperSetup();
void StepperLoop();
void writeProgram();
boolean readProgram();
void stepPan(int d);
void stepTilt(int d);
void stepDolly(int d);
void Run(int s);
void dumpProgram();
void dumpTest();
void PTDSetup();
void PTDLoop();
void StateMachineLoop();
#line 38 "C:\\Users\\chris\\OneDrive\\Documents\\Arduino\\RemoteXY Stuff\\PanTiltDollyVersion2\\PanTiltDollyVersion2.ino"
uint8_t RemoteXY_CONF[] =
{ 255,16,0,27,0,89,1,10,16,0,
130,1,8,1,84,7,29,130,1,8,
44,84,17,29,130,1,46,23,46,19,
not sure what I am doing wrong.....
Not sure how to accept an answer, but Delta_G gave a good solution. Thanks!
Have you tried just giving it your own forward declaration in a more appropriate place and see if that stops Arduino from trying to put it in for you? – Delta_G 1
Putting my own forward declarations fixed the issue.
fixed what the Arduino compiler could not do.

Use LiquidCrystal_I2C in a class on arduino

I want to make a class in cpp for arduino uno that writes on a display. I'm using the LiquidCrystal_I2C library but I can't use it in my class. I know how to do it without a class, but right now I want to build a class and I cant get it to work.
My .h file:
// WriteDisplay.h
#ifndef _WRITEDISPLAY_h
#define _WRITEDISPLAY_h
#if defined(ARDUINO) && ARDUINO >= 100
#include "arduino.h"
#else
#include "WProgram.h"
#endif
#include <Wire/Wire.h>
#include <LiquidCrystal_I2C2004V1/LiquidCrystal_I2C.h>
class WriteDisplayClass
{
public:
WriteDisplayClass();
void write(String text);
private:
LiquidCrystal_I2C lcd(0x27,20,4);
};
extern WriteDisplayClass WriteDisplay;
#endif
My .cpp:
#include "WriteDisplay.h"
WriteDisplayClass::WriteDisplayClass()
{
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
}
WriteDisplayClass::write(String text)
{
lcd.clear();
lcd.print(text);
}
WriteDisplayClass WriteDisplay;
My .ino:
#include "WriteDisplay.h"
WriteDisplayClass wdc;
void setup()
{
wdc.write("Hello World");
}
void loop()
{
}
I'm using AtmelStudio with Visual Micro. I'm getting it to work when I'm only using my .ino-file, but I can't do the same thing in cpp. I'm getting errors that LiquidCrystal_I2C.h can't be found and stuff like that. How should I do to get it to work the way I want it to? Or is it even possible?
Thanks for answer.
Sorry I misread the question the first time.
To use libraries in the .cpp file of an Arduino sketch you must also include them in the master .ino file. They are only compiled if found in the .ino
You can add the includes manually or use the "Project>Add/Import Sketch Library" menu item which will add them to the .ino for you.
Based on this post here the problem with your code is related the class being instantiated as global. The problem comes that the compiler doesn't guarantee the order of global variables processing, so in order to guarantee that the object concerning the display is executed lastly after all the library ones, you have to instantiate it in the setup() function!
The solution to your .ino code is to set a global pointer and then you assign the object inside the setup() function, like so:
#include "WriteDisplay.h"
WriteDisplayClass *wdc;
void setup()
{
wdc = new WriteDisplayClass();
wdc->write("Hello World");
}
void loop()
{
}

Serial.println within a class in Arduino

I'm trying to do Serial.println() within a class in the Arduino IDE. However, the compiler is saying that Serial was not declared in this scope. Here is the code:
Code in Menu.h
class Menu
{
public:
int options[4];
void test() {
Serial.println("here");
}
private:
};
Code in main file:
#include "Menu.h"
Menu menu;
void setup() {
Serial.begin(9600);
menu.test();
}
void loop() {
}
The right #include is probably added automatically by Arduino to your .pde. Try #include <WProgram.h> in the top of your Menu.h.
I'm not sure if the code snippet is complete (if it isn't, please post a complete one) but it looks like you forgot to include the appropriate header file which declares the class Serial.

Parameterless constructor

I am a fairly experienced .net developer but new to Arduino and C/C++ and I am trying to create my first library which is a simple driver for a 7 segment led display. I have many obtuse compiler errors but in the spirit of one thing at a time this is the first. I want to add a parameterless constructor to my class and when I do library compiles fine but when I try to use the class in a sketch the compiler gives me the rather obtuse "request for member 'setDigit' in 'sevenSegmentLed', which is of non-class type 'SevenSegmentLed()"
The simplest example code is below:
#ifndef SevenSegmentLed_h
#define SevenSegmentLed_h
#include "Arduino.h"
class SevenSegmentLed
{
public:
void setDigit(int digit);
SevenSegmentLed();
};
#endif
#include "Arduino.h"
#include "SevenSegmentLed.h"
SevenSegmentLed::SevenSegmentLed()
{
}
void SevenSegmentLed::setDigit(int digit)
{
}
#include "SevenSegmentLed.h"
SevenSegmentLed sevenSegmentLed();
void setup() {
sevenSegmentLed.setDigit(4);
}
void loop() {
// put your main code here, to run repeatedly:
}
However if I change the constructor signature to: SevenSegmentLed(int wtf); and instantiate it thus: SevenSegmentLed sevenSegmentLed(1); it compiles just fine. So as the parameter says, WTF?
I believe the issue is that this:
SevenSegmentLed sevenSegmentLed();
Is interpreted as a function declaration and not an initialization. Note that you can't have this problem with c# because you have the new keyword disambiguating for you so this particular problem is avoided.
To fix you can do 2 things:
Use the c++ uniform initialization syntax (introduced in newer c++ standard to avoid exactly your issue):
SevenSegmentLed sevenSegmentLed{};
Or use the following syntax:
SevenSegmentLed sevenSegmentLed;
The main benefit of the uniform syntax is that it's uniform. So for example if you have a constructor that takes an integer you can write it like this:
SevenSegmentLed sevenSegmentLed{1};
Generally speaking the uniform initialization syntax is preferable, when I was writing the c++ guideline at my work (mostly c# and php guys) I decided to go with this as it's the most clear and unambiguous.