Topic "Problème de class template ... "

Flux RSS des posts récents dans ce topic ( Flux Atom)


Pas de photo de profil

kollibar

Membre

#239 | Signaler ce message


Bonjour,

J’écris un code pour arduino. L'idée et d'avoir une librairie d'interface IO, en utilisant la librairie graphique Adafruit_GFX et y ajouter des fonctions clavier. Puis d'ajouter à tout ça un objet widget avec des "widgets" plus complet.

J'ai un problème avec une class template. J'immagine que j'ai oublié quelque chose dans l'écriture de ma class template, mais je sèche depuis hier… Pouvez vous jeter un coup d’œil pour m'aider? Merci beaucoup!

le message d'erreur:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[Tue Aug 30 16:01:17 2016] Processing megaatmega2560 (platform: atmelavr, board: megaatmega2560, framework: arduino)
--------------------------------------------------------------------------------
avr-g++ -o .pioenvs/megaatmega2560/src/main.o -c -fno-exceptions -fno-threadsafe-statics -std=gnu++11 -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=atmega2560 -DF_CPU=16000000L -DPLATFORMIO=021102 -DARDUINO_ARCH_AVR -DARDUINO_AVR_MEGA2560 -DARDUINO=10608 -I.pioenvs/megaatmega2560/FrameworkArduino -I.pioenvs/megaatmega2560/FrameworkArduinoVariant -I.pioenvs/megaatmega2560/Broches -I .pioenvs/megaatmega2560/SPI -I.pioenvs/megaatmega2560/PrintPGM -I.pioenvs/megaatmega2560/Adafruit_GFX_v1.0.2_NB8bits -I.pioenvs/megaatmega2560/PCD8544 -I.pioenvs/megaatmega2560/Clavier -I.pioenvs/megaatmega2560/IO_PCD8544_3touches -I.pioenvs/megaatmega2560/Widgets -Isrc src/main.cpp
avr-g++ -o .pioenvs/megaatmega2560/firmware.elf -Os -mmcu=atmega2560 -Wl,--gc-sections,--relax .pioenvs/megaatmega2560/src/main.o -L/hom/thom/.platformio/packages/ldscripts -L.pioenvs/megaatmega2560 -Wl,--start-group .pioenvs/megaatmega2560/libFrameworkArduinoVariant.a .pioenvs/megaatmega2560/libFrameworkArduino.a -lm .pioenvs/megaatmega2560/libBroches.a .pioenvs/megaatmega2560/libSPI.a .pioenvs/megaatmega2560/libPrintPGM.a .pioenvs/megaatmega2560/libAdafruit_GFX_v1.0.2_NB8bits .pioenvs/megaatmega2560/libPCD8544.a .pioenvs/megaatmega2560/libClavier.a .pioenvs/megaatmega2560/libIO_PCD8544_3touches.a .pioenvs/megaatmega2560/libWidgets.a -Wl,--end-group
.pioenvs/megaatmega2560/src/main.o: In function `loop':
/home/thom/Arduino/test_GFX/src/main.cpp:27: undefined reference to `Widgets<IO_PCD8544_3touches_SPI_software>::menuListeOuiNon(unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)'
.pioenvs/megaatmega2560/src/main.o: In function `__static_initialization_and_destruction_0':
/home/thom/Arduino/test_GFX/src/main.cpp:7: undefined reference to `Widgets<IO_PCD8544_3touches_SPI_software>::Widgets(IO_PCD8544_3touches_SPI_software&)'
collect2: error: ld returned 1 exit status
scons: *** [.pioenvs/megaatmega2560/firmware.elf] Error 1

le code du fichier main.cpp:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <Arduino.h>
#include <IO_PCD8544_3touches.h> // cette classe fusionne un objet Adafruit_PCD854 et un objet Clavier (de mon crû)
#include <Widgets.h> // la fameuse class de widget

IO_PCD8544_3touches_SPI_software display=IO_PCD8544_3touches_SPI_software(BROCHE_ECRAN_SCLK, BROCHE_ECRAN_SDIN, BROCHE_ECRAN_DC, BROCHE_ECRAN_CS, BROCHE_ECRAN_RESET); // Software SPI (slower updates, more flexible pin options):

Widgets<IO_PCD8544_3touches_SPI_software> widgets(display);

void setup(){
    display.begin();
    display.setContrast(50);
    display.display();
    display.setTextColor(BLACK, WHITE);
    display.setTextSize(1);
}

void loop(){
  uint8_t touche;
  display.aucuneTouche();

  touche=display.getTouche(-1);
  display.println(millis());
  display.print(touche,BIN);
  display.display();
  display.aucuneTouche();

  widgets.menuListeOuiNon();
  display.clearDisplay();
}

le code du header de la librairie concernée: (Widgets.h)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef __WIDGETS_H__
#define __WIDGETS_H__

#include <IO_PCD8544_3touches.h>
struct retourSelect {
  uint8_t touche;
  uint8_t result;
};

template<typename T>
class Widgets{
public:
  //Widgets();
  Widgets(T& _display);

  retourSelect menuListe(char* chaine, uint8_t nb, uint8_t taille = 15, uint8_t yMin = 0, uint8_t yMax = LCDHEIGHT, uint8_t xMin = 0, uint8_t xMax = LCDWIDTH, uint8_t hLigne = 1, uint8_t depart = 0, uint8_t textSize = 1, uint8_t actual = 0, uint8_t permissions = 0b10010000); // pour compatibilité avec l'ancienne forme
  retourSelect menuListeV2(void (*callback)(uint8_t, char*, uint8_t, void*), void* arg, uint8_t nb, uint8_t taille = 15, uint8_t yMin = 0, uint8_t yMax = LCDHEIGHT, uint8_t xMin = 0, uint8_t xMax = LCDWIDTH, uint8_t hLigne = 1, uint8_t depart = 0, uint8_t textSize = 1, uint8_t actual = 0, uint8_t permissions = 0b10010000);
  retourSelect menuListeOuiNon(uint8_t yMin = 0, uint8_t yMax = LCDHEIGHT, uint8_t xMin = 0, uint8_t xMax = LCDWIDTH, uint8_t hLigne = 1, uint8_t depart = 0, uint8_t textSize = 1, uint8_t permissions = 0b10010000);
protected:
  T* display;
};

void _creeLigneMenuListeV1(uint8_t i, char* chaine, uint8_t taille, void* arg);
void _creeLigneMenuListeOuiNon(uint8_t i, char* chaine, uint8_t taille, void* arg);
#endif

et le code de la librairie (Widgets.cpp):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "Widgets.h"

template<typename T>
Widgets<T>::Widgets(T& _display){
  display=&_display;
}

template<typename T>
retourSelect Widgets<T>::menuListeOuiNon(uint8_t yMin, uint8_t yMax, uint8_t xMin, uint8_t xMax, uint8_t hLigne, uint8_t depart, uint8_t textSize, uint8_t permissions) {
  return menuListeV2( _creeLigneMenuListeOuiNon, (void*)&yMin, 2, 4, yMin, yMax, xMin, xMax, hLigne, depart, textSize, 0, permissions);
}

template<typename T>
retourSelect Widgets<T>::menuListe(char* chaine, uint8_t nb, uint8_t taille, uint8_t yMin, uint8_t yMax, uint8_t xMin, uint8_t xMax, uint8_t hLigne, uint8_t depart, uint8_t textSize, uint8_t actual, uint8_t permissions) {
  /*   affiche une liste est retourne le numéro de l'item selectionné
        liste est un tableau de pointeur vers des chaine comprenant la chaine de caractère de l'item
        nb est le nombre d'élément dans la liste principale
        taille donne la taille des élements de la chaine /!\ y compris le bit de fin de chaine /!\
        yMin est le point de départ de la liste en graphique (par défaut 0)
        yMax est le bas de la liste (par défaut bas de l'écran)
        xMin ... idem en X
        xMax ... idem en X
        hLigne est la hauteur de la ligne en nb de caractère (càd 1 car = 8 pixels de haut), par defaut 1
        permissions indique les permissions pour quitter le menu (autre que sélection), par défaut TIMEOUT & BT_ESC

        /!\ si plusieurs lignes pour une chaine (càd hLigne!=0) compter un caractère en plus pour chaque ligne pour ajouter une fin de ligne
  */

  return menuListeV2( _creeLigneMenuListeV1, (void*)chaine, nb, taille, yMin, yMax, xMin, xMax, hLigne, depart, textSize, actual, permissions);
}

template<typename T>
retourSelect Widgets<T>::menuListeV2( void (*callback)(uint8_t, char*, uint8_t, void*), void* arg, uint8_t nb, uint8_t taille, uint8_t yMin, uint8_t yMax, uint8_t xMin, uint8_t xMax, uint8_t hLigne, uint8_t depart, uint8_t textSize, uint8_t actual, uint8_t permissions) {
  /*   affiche une liste est retourne le numéro de l'item selectionné
        liste est un tableau de pointeur vers des chaine comprenant la chaine de caractère de l'item
        nb est le nombre d'élément dans la liste principale
        taille donne la taille des élements de la chaine /!\ y compris le bit de fin de chaine /!\
        yMin est le point de départ de la liste en graphique (par défaut 0)
        yMax est le bas de la liste (par défaut bas de l'écran)
        xMin ... idem en X
        xMax ... idem en X
        hLigne est la hauteur de la ligne en nb de caractère (càd 1 car = 8 pixels de haut), par defaut 1
        permissions indique les permissions pour quitter le menu (autre que sélection), par défaut TIMEOUT & BT_ESC

        /!\ si plusieurs lignes pour une chaine (càd hLigne!=0) compter un caractère en plus pour chaque ligne pour ajouter une fin de ligne
  */
    
    // Je vire le code parce que ça fait trop lourd...
}

void _creeLigneMenuListeV1(uint8_t i, char* chaine, uint8_t taille, void* arg) {
  char* chaineCom = (char*)arg;
  strcpy(chaine, &chaineCom[i * taille]);
  return;
}

void _creeLigneMenuListeOuiNon(uint8_t i, char* chaine, uint8_t taille, void* arg) {
  switch (i) {
    case 0:
      //strcpy_P(chaine, TXT_OUI);
      strcpy(chaine,"OUI");
      break;
    case 1:
      //strcpy_P(chaine, TXT_NON);
      strcpy(chaine,"NON");
      break;
    default:
      break;
  }
}

//template<typename T>
//Widgets<T>::Widgets(){
//  display=NULL;
//}

Derniére modification le par kollibar


Photo de profil de skywodd

skywodd

Membre

Membre du staff

#244 | Signaler ce message


Bonjour,

Comment les fichiers sont organisés au sein du projet ? Tout est dans le même dossier que le fichier .ino ?

Les undefined reference sont souvent liés à un probléme d'include relatif (il y a une différence entre "xxx.h" et <xxx.h>).


Pas de photo de profil

kollibar

Membre

#245 | Signaler ce message


Bonjour,

Comment les fichiers sont organisés au sein du projet ? Tout est dans le même dossier que le fichier .ino ?

Les undefined reference sont souvent liés à un probléme d'include relatif (il y a une différence entre "xxx.h" et <xxx.h>).

par skywodd

Hello, en fait j'ai trouvé, ou plutôt j'ai posé la question sur le forum de developpez.net et j'ai eu une super réponse: http://www.developpez.net/forums/d1600642/c-cpp/cpp/langage/probleme-class-template/

Du coup, j'ai opté pour la solution simple, j'ai basculé tout le code de la class présent dans le .cpp vers le .h.

Merci :)