¿Por qué no puedo declarar una clase en otra pestaña en Arduino IDE?

20

Quería mover parte de mi código a una segunda pestaña en el IDE de Arduino, para mantener las cosas mejor organizadas. Al principio, solo intenté mover una función, y parecía funcionar bien. Podía llamar a la función desde la setup()función en mi pestaña principal, y no hubo problemas al compilar o cargar.

Sin embargo, intenté poner una clase completa en la segunda pestaña, y de repente ya no funcionó. Por ejemplo:

Pestaña 1:

TestClass obj;

void setup()
{
    obj.init();
}

void loop()
{
    //...
}

Pestaña 2:

class TestClass
{
public:
    void init()
    {
        //...
    }
};

Cuando intenté compilar esto, me dio los siguientes errores:

tab1:1: error: 'TestClass' does not name a type
tab1.ino: In function 'void setup()':
tab1:5: error: 'obj' was not declared in this scope

¿Por qué reconoce una función en otra pestaña, pero no una clase? ¿Hay alguna manera de que funcione en el IDE de Arduino, o necesito usar una alternativa como Eclipse?

Peter Bloomfield
fuente
¿Es esta la totalidad del código? ¿Cuáles son los nombres de los archivos? ¿No hay directivas de preprocesador como #include?
asheeshr
Sí, esa es la totalidad del código. Las pestañas se nombran tab1y tab2respectivamente. Los nombres se configuraron utilizando el IDE, por lo que los archivos subyacentes son ambos .ino.
Peter Bloomfield
Estoy empezando a odiar la jiggery pokery que hace Arduino IDE. Lo que agrega en la facilidad de uso sobre AVR lo quita al romper cosas como esta.
Cybergibbons

Respuestas:

13

No es posible declarar y usar clases declaradas en un .pdearchivo en otro .pdearchivo desde el IDE de Arduino.

Una solución alternativa es convertir el segundo archivo en un archivo fuente C ++ ( .cpp) y luego agregar una #include "<filename>"directiva al comienzo del primer archivo.


Este código se compila correctamente:

Pestaña 1:

#include "test.cpp"

TestClass obj;

void setup()
{
    obj.init();
}

void loop()
{
    //...
}

test.cpp:

class TestClass
{
public:
    void init()
    {
        //...
    }
};
Asheeshr
fuente
Gracias por la solución. Funciona para el ejemplo básico, pero desafortunadamente no funciona si agrego llamadas específicas de Arduino en el archivo .cpp. Por ejemplo, si TestClass::init()intenta llamar pinMode(), el compilador se queja de que pinModeno se declaró en este ámbito. ¿Hay alguna forma de acceder a las funciones de Arduino en mi clase?
Peter Bloomfield
66
@ PeterR.Bloomfield Agregue un #include <Arduino.h>a la parte superior del .cpparchivo.
asheeshr
1
Creo que no es bueno enseñar a otros a incluir archivos de origen ( #include "test.cpp"). Funciona, pero puede frenar la comprensión del proceso de vinculación. Solo se deben incluir archivos de encabezado.
Marte
1
Estoy de acuerdo con @Mars: una mejor solución es colocar la declaración de clase en un archivo .h, y la definición (implementación) en un archivo .cpp. Entonces tienes dos archivos adicionales en el proyecto. Esta es en realidad la forma normal de manejar las clases.
Nick Gammon
6

La forma en que funciona el IDE de Arduino es que compila su código (el código que escribe en el IDE) como el código "principal". Luego, extrae el código de todas las bibliotecas que ha importado y lo compila junto con el código principal. Para hacer lo que está sugiriendo, necesitaría crear una biblioteca para Arduino.

Aquí hay más información sobre las bibliotecas Arduino:

http://arduino.cc/en/Guide/Libraries

Y aquí hay algunos sobre cómo crear una biblioteca:

http://arduino.cc/en/Hacking/LibraryTutorial // este es el más fácil de entender imo
http://playground.arduino.cc/Code/Library
http://www.divilabs.com/2013/03/ write-your-own-arduino-library.html #

Aquí hay una biblioteca de ejemplo que escribí https://github.com/jamolnng/Arduino/tree/master/libraries/ShiftRegister, como puede ver, no hay ningún problema al llamar a las funciones de Arduino desde el archivo .cpp (lo sé, he probó la biblioteca)

Jesse Laning
fuente
3
También es posible crear .hy .cpparchivos en su proyecto principal, sin tener que crear una biblioteca separada.
microtherion