Por que não posso declarar uma classe em outra guia no Arduino IDE?

20

Eu queria mover parte do meu código para uma segunda guia no IDE do Arduino, para manter as coisas melhor organizadas. No começo, eu apenas tentei mover uma função, e parecia funcionar bem. Eu poderia chamar a função a partir da setup()função na minha guia principal e não houve problemas ao compilar ou fazer upload.

No entanto, tentei colocar uma classe inteira na segunda guia e, de repente, não funcionou mais. Por exemplo:

Guia 1:

TestClass obj;

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

void loop()
{
    //...
}

Guia 2:

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

Quando tentei compilar isso, ocorreram os seguintes erros:

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 que ele reconhece uma função em outra guia, mas não em uma classe? Existe uma maneira de fazê-lo funcionar no Arduino IDE ou preciso usar uma alternativa como o Eclipse?

Peter Bloomfield
fonte
É este o conjunto do código? Quais são os nomes dos arquivos? Não existem diretivas de pré-processador como #include?
21814 asheeshr
Sim, essa é a totalidade do código. As guias são nomeadas tab1e tab2respectivamente. Os nomes foram definidos usando o IDE; portanto, os arquivos subjacentes são ambos .ino.
Peter Bloomfield
Estou começando a odiar a brincadeira que o IDE do Arduino faz. O que ele adiciona na facilidade de uso em relação ao AVR leva a quebrar coisas como essa.
Cybergibbons 10/03/2014

Respostas:

13

Não é possível declarar e usar classes declaradas em um .pdearquivo em outro .pdearquivo no IDE do Arduino.

Uma solução alternativa é transformar o segundo arquivo em um arquivo de origem C ++ ( .cpp) e adicionar uma #include "<filename>"diretiva no começo do primeiro arquivo.


Este código compila corretamente:

Guia 1:

#include "test.cpp"

TestClass obj;

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

void loop()
{
    //...
}

test.cpp:

class TestClass
{
public:
    void init()
    {
        //...
    }
};
asheeshr
fonte
Obrigado pela solução alternativa. Ele funciona no exemplo básico, mas infelizmente não funciona se eu adicionar chamadas específicas do Arduino no arquivo .cpp. Por exemplo, se TestClass::init()tentar chamar pinMode(), o compilador reclama que pinModenão foi declarado neste escopo. Existe uma maneira de acessar as funções do Arduino na minha classe?
Peter Bloomfield
6
@ PeterR.Bloomfield Adicione um #include <Arduino.h>ao topo do .cpparquivo.
21814 asheeshr
11
Eu acho que não é bom ensinar outras pessoas a incluir arquivos de origem ( #include "test.cpp"). Funciona, mas pode impedir a compreensão do processo de vinculação. Somente arquivos de cabeçalho devem ser incluídos.
Marte
11
Concordo com o @Mars - uma solução melhor é colocar a declaração da classe em um arquivo .h e a definição (implementação) em um arquivo .cpp. Então você tem dois arquivos extras no projeto. Esta é realmente a maneira normal de lidar com classes.
Nick Gammon
6

A maneira como o Arduino IDE funciona é que ele compila seu código (o código que você escreve no IDE) como o código "principal". Em seguida, ele extrai o código de todas as bibliotecas importadas e o compila junto com o código principal. Para fazer o que você está sugerindo, seria necessário criar uma biblioteca para o Arduino.

Aqui estão mais algumas informações sobre as bibliotecas do Arduino:

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

E aqui estão algumas dicas sobre como criar uma biblioteca:

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

Aqui está um exemplo de biblioteca que escrevi https://github.com/jamolnng/Arduino/tree/master/libraries/ShiftRegister, como você pode ver, não há problema em chamar funções do Arduino a partir do arquivo .cpp (eu sei, eu testou a biblioteca)

Jesse Laning
fonte
3
Também é possível apenas criar .he .cpparquivos em seu projeto principal, sem ter que criar uma biblioteca separada.
microtherion