Probleme mit den bekanntmachen von Funktionen in Header bei C++

Gast #6936131
Lesenswert?

Hallo ihr lieben,

ich habe leider bei meinen Hobbyprogrammieren ein Problem mit den 
Headerdateien.

Ich habe leider aus speicherplatzgründen eine Klasse in einzelne 
Funktionen auflösen müssen, da der Arbeitsspeicher und Flashspaicher 
nicht ausreichend ist.
Desshalb möchte ich in den namensraum std einfach ein paar Funktionen 
haben.
Innerhalb der Funktionen lese und schribe ich mehrmals in vershiedene 
Variablen aus den Nahmensraum.

Leider schaffe ich es nicht die Variablen und Funktionen in einer Header 
Datei zu hinderlegen.
Die Beispiele und tutorials haben bei mir auch nichts geholfen, da sie 
lediglich das Problem im Kontext von Klassendefinitionen abhandeln.

Die Fehlermeldungen sind:
../Core/Src/Parser.cpp:1411:29: error: call of overloaded 
'IsNumeric(char*&)' is ambiguous
../Core/Src/Parser.cpp:1438:35: error: call of overloaded 
'strToU32(char*&)' is ambiguous
../Core/Src/Parser.cpp:1443:38: error: call of overloaded 
'IsNumeric(char*&)' is ambiguous
../Core/Src/Parser.cpp:1468:31: error: call of overloaded 
'IsNumeric(char*&)' is ambiguous
../Core/Src/Parser.cpp:1469:36: error: call of overloaded 
'strXToU32(char*&)' is ambiguous
../Core/Src/Parser.cpp:1474:39: error: call of overloaded 
'IsNumeric(char*&)' is ambiguous

Hat jemand ein Tipp wie ich die Fehlermeldungen beseitigen kann?
Leider hat es mit extern deklaratonen wie in C üblich nicht fuktioniert.
Genau so wie wenn ich versuche die Probleme mit std:: auf zu lösen.
Dann bekomme ich 'multiple definition' Fehler.

Parser.cpp
1
#include <content_xml.hpp>
2
#include <Parser.hpp>
3
#include <stdint.h>
4
#include <stdlib.h>
5
#include <string.h>
6

7
using namespace std;
8

9
extern volatile uint32_t Memory[1024];
10

11

12
void ParserChar(char *ptr, uint16_t Len){
13
  //...
14
}
15

16
void ParserMem(uint32_t *ptr){
17
  //...
18
}
19

20

21
uint8_t StartParserXml(char *ptr, uint16_t Len){
22
    //...
23
    return 1;
24
}
25

26
uint8_t StartParserByte(uint32_t *ptr){
27
    //...
28
    return 1;
29
}
30

31
ClContent_xml** contentAdd(uint16_t inkrement){
32
    //...
33
}
34

35
uint8_t StartCheckXml(void){
36
  //...
37
    return 1;
38
}
39

40
uint8_t StartGenerateByte(uint32_t* ptr, uint16_t MaxLen){
41
  //...
42
    return 1;
43
}
44

45
uint32_t getByte(uint16_t i){
46
    //...
47
    return Value;
48
}
49

50
uint8_t NumData(char* ptr){
51
    //...
52
    return Nummer;
53
}
54

55
uint8_t IsNumeric(char* ptr){
56
    //...
57
    return 0;
58
}
59

60
uint8_t strToU8(char* ptr){
61
    //...
62
    return Val;
63
}
64

65
uint16_t strToU16(char* ptr){
66
    //...
67
}
68

69
uint32_t strToU32(char* ptr){
70
    //...
71
    return Val;
72
}
73

74
uint32_t strXToU32(char* ptr){
75
    //...
76
    return Val;
77
}
78

79
uint16_t* strToU16Array(char* ptr){
80
    uint16_t Val = 0;
81
    uint8_t Num = 0;
82
    uint8_t st = 0;
83
    uint16_t *Array, *LArray;
84
    char *Sptr;
85
    Sptr = ptr;
86

87
    // Anzahl der Zahlen ermitteln
88
    do{
89
        switch(*ptr){
90
        case '0':
91
        case '1':
92
        case '2':
93
        case '3':
94
        case '4':
95
        case '5':
96
        case '6':
97
        case '7':
98
        case '8':
99
        case '9':
100
            if((st & 0x02) == 0x00){
101
                Num++;
102
                st |= 0x02;
103
            }
104
            break;
105
        case ' ':
106
        case ',':
107
            if((st & 0x02) == 0x02){
108
                st = (st & ~0x02);
109
            }
110
            break;
111
        default:
112
            st |= 0x01;
113
            break;
114
        }
115
        ptr++;
116
    }while((st & 0x01) == 0);
117

118
    Array = new uint16_t[Num];
119
    LArray = Array;
120

121
    for(uint8_t i = 0; i < Num; i++){
122
        while((*Sptr == ' ') || (*Sptr == ',')){
123
            Sptr++;
124
        }
125

126
        *LArray = strToU16(Sptr);
127

128
        //printf("\n%i, Wert: %i, Adresse: 0x%x", i, *LArray, LArray);
129

130
        while(IsNumeric(Sptr)){
131
            Sptr++;
132
        }
133
        LArray++;
134
    }
135
    return Array;
136
}
137

138
uint32_t* strToU32Array(char* ptr, uint8_t Num){
139
    uint32_t Val = 0;
140
    uint8_t st = 0;
141
    uint32_t *Array, *LArray;
142
    char *Sptr;
143
    Sptr = ptr;
144

145
    Array = new uint32_t[Num];
146
    LArray = Array;
147

148
    for(uint8_t i = 0; i < Num; i++){
149
        // Leerzeichen ignurieren
150
        while(*ptr == ' '){
151
            ptr++;
152
        }
153
        if(1 == IsNumeric(ptr)){
154
            *LArray = strToU32(ptr);
155
            LArray++;
156
            do{
157
                ptr++;
158
            }while(1 == IsNumeric(ptr));
159
        }
160
        else{
161
            return Array;
162
        }
163
    }
164
    return Array;
165
}
166

167
uint32_t* strXToU32Array(char* ptr, uint8_t Num){
168
    uint32_t Val = 0;
169
    uint8_t st = 0;
170
    uint32_t *Array, *LArray;
171

172
    Array = new uint32_t[Num];
173
    LArray = Array;
174

175
    for(uint8_t i = 0; i < Num; i++){
176
        // Leerzeichen ignurieren
177
        while((*ptr == ' ') || (*ptr == ',')){
178
            ptr++;
179
        }
180

181
        if((1 == IsNumeric(ptr))){
182
            *LArray = strXToU32(ptr);
183
            LArray++;
184
            do{
185
                ptr++;
186
            }while((1 == IsNumeric(ptr)) || (*ptr == 'x') || (*ptr == 'X'));
187
        }
188
        else{
189
            return Array;
190
        }
191
    }
192
    return Array;
193
}
194

195
uint16_t setByteU8(uint8_t Value, uint16_t Inkrement){
196
    //...
197
    return Inkrement + 1;
198
}
199

200
uint16_t setByteU16(uint16_t Value, uint16_t Inkrement){
201
    //...
202
    return Inkrement + 2;
203
}
204

205
uint16_t setByteU32(uint32_t Value, uint16_t Inkrement){
206
    //...
207
    return Inkrement + 4;
208
}
209

210
uint16_t setByte(void){
211
    // MemByte in das Flash schreiben
212
    return 0;
213
}

Parser.hpp
1
#ifndef PARSER_H
2
#define PARSER_H
3

4
#include <stdint.h>
5
#include <content_xml.hpp>
6
#include <loopdef.hpp>
7
#include <trigger.hpp>
8

9
namespace std{
10
  void ParserChar(char*, uint16_t);
11
  void ParserMem(uint32_t*);
12

13
  // Funktionsprototypen
14
  uint8_t pstringp(char*, uint16_t);
15
  uint8_t GetValue(void);
16

17
  // Variablen
18
  ClContent_xml **contentXml;
19
  uint8_t contentXml_Load;
20

21
  uint8_t StartParserXml(char*, uint16_t);
22
  uint8_t StartCheckXml(void);
23
  uint8_t StartParserByte(uint32_t*);
24
  uint8_t StartGenerateByte(uint32_t*, uint16_t);
25
  uint32_t *BytePtr;
26

27
  uint8_t NumData(char*);
28
  uint8_t IsNumeric(char*);
29
  uint8_t strToU8(char*);
30
  uint16_t strToU16(char*);
31
  uint32_t strToU32(char*);
32
  uint32_t strXToU32(char*);
33

34
  uint16_t* strToU16Array(char*);
35
  uint32_t* strToU32Array(char*, uint8_t);
36
  uint32_t* strXToU32Array(char*, uint8_t);
37

38
  char StrGreet[30];
39

40
  // Variablen
41
  char* StringPtr;
42
  uint16_t StringLen;
43

44
  // Prototypen
45
  ClContent_xml **contentAdd(uint16_t);
46
  uint32_t getByte(uint16_t);
47
  uint16_t setByteU8(uint8_t, uint16_t);
48
  uint16_t setByteU16(uint16_t, uint16_t);
49
  uint16_t setByteU32(uint32_t, uint16_t);
50
  uint16_t setByte(void);
51

52
  uint32_t MemByte;
53

54
  ClLoopdef **StmLoop;
55
  uint8_t StmLoopLoad;
56
  ClTrigger **StmTrigger;
57
  uint8_t StmTriggerLoad;
58
}
59
#endif // PARSER_H

Vielen Dank und Frohes neues Jahr

Philip
#6936156
Lesenswert?

Die Fehler stecken in den Zeilen ab 1411. Dein Quellcode zeigt die 
nicht. Dazu schreibst du von Problemen mit Header-Dateien, zeigst aber 
eine .cpp
Wie soll man da helfen?

Und als letztes steht über jedem Beitrag in Fett:

> Wichtige Regeln - erst lesen, dann posten!
> Groß- und Kleinschreibung verwenden
> Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Bevor du jetzt hier 2000 Zeilen in das Textfeld ballern willst.

Oliver
Gast #6936179
Lesenswert?

Ich habe hier nicht nur eine *.cpp Datei gekürz eingestellt sondern 
darunter auch die *.hpp Datei (ungekürzt) also erst lesen.

Die Fehlermeldungen habe ich leider vergessen an den gekürzten Inhalt 
anzupassen...
Inzwischen habe ich wie von  Mombert H vorgeschagen das ganze in ein 
eigenen Namensraum verschoben.
Dadurch haben sich die Fehlermeldungen geändert:
../Core/Src/Parser.cpp:126:32: error: call of overloaded 
'strToU16(char*&)' is ambiguous
../Core/Src/Parser.cpp:130:29: error: call of overloaded 
'IsNumeric(char*&)' is ambiguous
../Core/Src/Parser.cpp:153:30: error: call of overloaded 
'IsNumeric(char*&)' is ambiguous
../Core/Src/Parser.cpp:154:35: error: call of overloaded 
'strToU32(char*&)' is ambiguous
../Core/Src/Parser.cpp:158:38: error: call of overloaded 
'IsNumeric(char*&)' is ambiguous
(Die Zeilennummern sind an den gekürzten Code angepasst).
#6936270
Lesenswert?

Philip schrieb:
> Hat jemand ein Tipp wie ich die Fehlermeldungen beseitigen kann?

In deiner hpp-Datei sind die Funktionen im Namespace, in der cpp-Datei 
sind sie außerhalb davon.

Philip schrieb:
> Ich habe hier nicht nur eine *.cpp Datei gekürz eingestellt sondern
> darunter auch die *.hpp Datei (ungekürzt) also erst lesen.

Es ging darum, dass du so langen Code nicht inline in dein Posting 
stecken sollst, sonst als separate Dateien anhängen.
Gast #6936354
Lesenswert?

Bei mir verschwinden die Fehler wenn ich die Funktionen mit dem Schema 
'Namensraum::Funktionsname(){}' definiere.
Klingt ja Logisch...

Leider habe bekomme ich statt dessen 'multiple definition of' Fehler:

c:\st\stm32cubeide_1.3.0\stm32cubeide\plugins\com.st.stm32cube.ide.mcu.e 
xternaltools.gnu-tools-for-stm32.9-2020-q2-update.win32_2.0.0.2021053113 
46\tools\arm-none-eabi\bin\ld.exe: 
./Core/Src/maincpp.o:(.bss._ZN6Parser14StmTriggerLoadE+0x0): multiple 
definition of `Parser::StmTriggerLoad';
./Core/Src/Parser.o:(.bss._ZN6Parser14StmTriggerLoadE+0x0): first 
defined here

Für die folgenden Variablen in einer Funktion aus maincpp.cpp.
In der Datei habe ich die Datei Parser.hpp includiert.
1
Parser::contentXml = nullptr;
2
Parser::contentXml_Load = 0;
3
Parser::BytePtr = nullptr;
4
Parser::StringPtr = nullptr;
5
Parser::StringLen = 0;
6
Parser::MemByte = 0;
7
Parser::StmLoop = nullptr;
8
Parser::StmLoopLoad = 0;
9
Parser::StmTrigger = nullptr;
10
Parser::StmTriggerLoad = 0;

Die einzige Definition von den Variablen habe habe ich in der 
Headerdatei Parser.hpp gemacht.
Header guards sind ja gundlegender Standart bei der Programmierung mit C 
und C++.

Unter C hätte ich in der Headerdatei in ähnlichen Kontext einfach den 
Prototypen extern vorangestellt.
Ähnliches habe ich unter C++ noch nicht gesehen...
#6936358
Lesenswert?

Philip schrieb:
> Die einzige Definition von den Variablen habe habe ich in der
> Headerdatei Parser.hpp gemacht.
> Header guards sind ja gundlegender Standart bei der Programmierung mit C
> und C++.
>
> Unter C hätte ich in der Headerdatei in ähnlichen Kontext einfach den
> Prototypen extern vorangestellt.
> Ähnliches habe ich unter C++ noch nicht gesehen...

Du solltest dir ein Ordentliches Buch zulegen und lesen. Der Unterschied 
zwischen Definition und Deklaration ist ein ziemlich wichtiges Konzept 
in C und C++.
#6936361
Lesenswert?

Philip schrieb:
> Die einzige Definition von den Variablen habe habe ich in der
> Headerdatei Parser.hpp gemacht.
> Header guards sind ja gundlegender Standart bei der Programmierung mit C
> und C++.

Ja, und daher wird pro Objektdatei die fragliche Funktion nur einmal 
erzeugt. Was für den Linker dann immer noch viel zu viele sind, so daß 
der sich zu Recht beschwert.

Da du aber immer ich nicht den Code zeigst, der zu den Fehlermeldungen 
passt, musst du halt weiter rätseln.

Oliver
#6936375
Lesenswert?

Philip schrieb:
> Die einzige Definition von den Variablen habe habe ich in der
> Headerdatei Parser.hpp gemacht.

Da gehört sie aber nicht hin. Dort darf nur die Deklaration hin, nicht 
die Definition.

> Header guards sind ja gundlegender Standart bei der Programmierung mit C
> und C++.

Die helfen nur gegen mehrfaches Einbinden in der selben .cpp-Datei.

> Unter C hätte ich in der Headerdatei in ähnlichen Kontext einfach den
> Prototypen extern vorangestellt.

Genau das musst du in C++ auch tun.
Gast #6944688
Lesenswert?

Hallo,
Sorry habe die Begriffe Definition und Deklaration verwechselt...
Peinlich wenn man das den Kollegen immer vorhält wenn ihnen das 
passiert.

Ich habe mich in C++ schon eingelesen, aber mir in den Fall nicht viel 
herleiten können.
Leider habe ich bei der Suche im Internet keine für mich 
nachvollziehbare Beispiele hierfür gefunden, daraufhin habe ich nach 
lösungen von ähnlichen Problemen in den KiCad Code gesucht, aber auch da 
nichts gefunden...

Wenn ich wie im letzten Beitrag vorgeschlagen in dem Headerfile das 
schlüsselwort extern einfüge steigt die Anzahl der Fehler bei den 
versuch zu Kompilieren auf 42 an.
Für die Variablen ist jeweils die Fehlermeldung "undefined reference to 
'Parser::Variablenname'".

Grüße

Philip
#6945077
Lesenswert?

Philip schrieb:
> Ok das ist dann doch ein Rückschritt zu C...
> Da reichen die extern Deklarationen in den Headerfiles einfach aus.

Nein. Auch in C muss die Variable definiert sein. "extern" heißt, dass 
die Variable irgendwo anders definiert ist. Damit das funktioniert, muss 
sie auch irgendwo anders definiert sein. Das ist in C und C++ gleich.
#6945082
Lesenswert?

Philip schrieb:
> Ich habe mich in C++ schon eingelesen, aber mir in den Fall nicht viel
> herleiten können.

Das Thema ist allergrundglegenstes C/C++-Basiswissen. Und das kommt 
alleine hier im Forum so oft, da ist die Forensuche anscheinend 
überfordert.

Ich habe daher mal für dich bei google inc in Kalifornien angefragt, ob 
die das Thema mal auf Microcontroller.net recherchieren können. Sie 
konnten...

https://www.google.com/search?q=c+header+globale+variablen+extern+site:www.mikrocontroller.net&client=firefox-b-d&sa=X&ved=2ahUKEwiD37HT9LX1AhXuhv0HHeMsBSkQrQIoBHoECAYQBQ&biw=1536&bih=739&dpr=1.25

Oliver
Gast #6945842
Lesenswert?

Ok vielen Dank euch!

Ich das ist jetzt der Punkt bei dem es bei mir gehangen hat...

Ich weis das in C streng genommen das auch so ist mir Deklaration und 
extern Deklaration, wobei bei mir sich die Compiler noch nicht beschwert 
haben wen ich lediglich extern deklarationen erstellt habe.

Beruflich habe ich mit den Sprachen C und Matlab M-Script / Simulink 
zutuhen.
Bei C eigendlich sogar in zeimliche Tiefe da ich regelmäsig statische 
Code Analysen auswerte...

Grüße

Philip

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren