Forum: Compiler & IDEs Probleme zwischen C++ und C Projekt Einbindung Funktion


von Robert P. (Firma: ---) (ausmilkel)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe bisher C Projekte im AVR Studio erstellt und wollte jetzt ein 
C++ Projekt erstellen.
Nun habe ich folgendes Problem beim compilieren vom C++ Projekt:
1
Error  2  undefined reference to `test_Buttons()'  D:\Tools\AVR\TESTcpp\ATmega1281_Cpp\ATmega1281_Cpp\Debug/.././ATmega1281_Cpp.cpp  20  1  ATmega1281_Cpp

Es scheint als kann AVR Studio die Funktion nicht finden.

Die Hauptdatei (ATmega1281_Cpp.cpp ) sieht folgendermaßen aus
1
#include  <avr/io.h>    // avrgcc Bibliothek
2
#include   <stdint.h>    // avrgcc Bibliothek
3
#include  <stdlib.h>
4
5
#include "../ATmega1281_Cpp/Libraries/Lib_Peripheral/BUTTON.H"
6
7
8
int main(void)
9
{
10
    while(1)
11
    {
12
        test_Buttons();
13
    
14
    //TODO:: Please write your application code 
15
    
16
    return 0;
17
    }
18
}

Button.c
1
#include <stdint.h>
2
#include "BUTTON.H"
3
4
void test_Buttons(void)
5
{
6
  
7
  uint32_t testbutton = 5;
8
  
9
}

Button.h
1
#ifndef BUTTON_H
2
#define BUTTON_H
3
4
#include <stdint.h>
5
#include "../Lib_MCU/general_config.h"
6
7
8
void test_Buttons(void);
9
10
11
#endif

Pfad in "Toolchain -> AVR/GNU C Compiler -> Directories " wurde 
angegeben.

Komischerweise kann ich das ganze in einem C Projekt ohne Probleme 
kompilieren (gleicher Code + Struktur)...

Ich habe bisher nur den Unterschied bei der Compiler Version gefunden 
(ich denke wegen C und C++ Projekt)

C Projekt
1
Invoking: AVR/GNU Linker : 4.8.1
2
  "C:\Program Files (x86)\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.1056\avr8-gnu-toolchain\bin\avr-gcc.exe"

C++ Projekt
1
Invoking: AVR8/GNU Linker : 4.8.1
2
  "C:\Program Files (x86)\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.1056\avr8-gnu-toolchain\bin\avr-g++.exe"

Anbei auch nochmals die Dateien für C und C++.
Wer kann mir weiterhelfen?

Gruß,
Robert

: Bearbeitet durch User
von Juergen (Gast)


Lesenswert?

In Buttons.h:
1
#ifdef __cplusplus
2
extern "C" {
3
#endif
4
5
void test_Buttons(void);
6
7
[... weitere Deklationen ...]
8
9
#ifdef __cplusplus
10
}
11
#endif

Und bitte informiere dich über Suchpfade für Include-Dateien. Sowas
1
#include "../Lib_MCU/general_config.h"
macht Augenschmerzen.

von temp (Gast)


Lesenswert?

Das liegt daran, dass C++ aus dem Funktionsnamen "test_Buttons" einen 
eigenen internen Namen macht an dem nach bestimmten Regeln auch die 
Funktionsparameter mit in den Namen eingehen. Kannst du die in der 
map-Datei ansehen. Oder nach "name mangling in c++" googeln, das 
verschafft Klarheit.
Als Lösung des Problems wird oft in den C-Headerdateien extern "C" 
verwendet, wenn sie unter C++ includet werden. Bei dir würde das so 
aussehen:
1
#ifndef BUTTON_H
2
#define BUTTON_H
3
4
#include <stdint.h>
5
#include "../Lib_MCU/general_config.h"
6
7
#ifdef __cplusplus
8
extern "C" {
9
#endif
10
11
12
void test_Buttons(void);
13
14
15
#ifdef __cplusplus
16
}
17
#endif
18
19
20
#endif

von Robert P. (Firma: ---) (ausmilkel)


Lesenswert?

Hallo temp(Gast),
Hallo Jürgen,

danke für das feedback. Ich glaub jetzt hat es Klick gemacht, 
zumindestens teilweise.

>Das liegt daran, dass C++ aus dem Funktionsnamen "test_Buttons" einen
>eigenen internen Namen macht an dem nach bestimmten Regeln auch die
>Funktionsparameter mit in den Namen eingehen. Kannst du die in der
>map-Datei ansehen.

tatsächlich habe ich jetzt sowas im map file gefunden nachdem ich meine 
Funktion "test_Buttons()" in ein .cpp abgelegt habe und dann alles 
kompiliert habe.
1
 .text._Z12test_Buttonsv
2
                0x000000a6        0x2 Libraries/Lib_Peripheral/BUTTON.o
3
                0x000000a6                _Z12test_Buttonsv

das heisst hier sieht man jetzt das Ergebnis vom "name mangling in c++" 
(_Z12test_Buttonsv)?!
Im Vergleich noch mal das .map file nach dem Kompilieren im C Projekt
1
.text.test_Buttons
2
                0x000000a6        0x2 Libraries/Lib_Peripheral/Button.o
3
                0x000000a6                test_Buttons
4
                0x000000a8                . = ALIGN (0x2)

Was ich noch nicht verstehe ist, warum das bei einem .c source file im 
C++ Projekt im Endeffekt nicht fuktioniert. Die Funktion ist doch genau 
gleich nur in einem .c file verpackt und natürlich ohne dem hier
1
 
2
#ifdef __cplusplus
3
extern "C" {
4
#endif

bzw. warum passiert dann anderes wenn die Funktion in einem .cpp file 
verpackt ist ?
Jetzt mal etwas Orakeln meinerseits:
hängt das mit den Unterschieden für Funktionen zwischen C und C++ 
zusammen (z. Bsp. Überladen von Funktionen nur in C++) ?

@Jürgen:


>Und bitte informiere dich über Suchpfade für Include-Dateien. Sowas
>#include "../Lib_MCU/general_config.h"
>macht Augenschmerzen.

wurde jetzt auch von mir verstanden und umgesetzt ;-)

Gruß,
Robert

von Sebastian V. (sebi_s)


Lesenswert?

Robert P. schrieb:
> hängt das mit den Unterschieden für Funktionen zwischen C und C++
> zusammen (z. Bsp. Überladen von Funktionen nur in C++) ?

Genau. In C++ gibt es allerhand neue Features wie Namespaces, Klassen 
und Überladen von Funktionen. Und dort muss man natürlich dafür sorgen, 
dass die Funktion A::foo(int) nicht mit B::foo(int) kollidiert. Für den 
Linker werden daher diese Infos die Funktionsnamen eingebaut.

von Hans W. (Firma: Wilhelm.Consulting) (hans-)


Lesenswert?

Naja
1
void test_Buttons(void);

könnte es auch als
1
bool test_Buttons();
2
bool test_Buttons(&int);

geben... zumindest in C++.

Mit dem extern C machst du aus der Funktion eine C-Funktionen. Damit 
hast du den Nachteil, dass es nur 1ne implementierung gibt, dafür kannst 
du sie Problemlos aus C aufrufen (sonst müsstest du trampoline oä 
verwenden).

btw: "void foo(void)" war schon in ur-C "falsch"/unnötig...

73

von Rolf M. (rmagnus)


Lesenswert?

Hans W. schrieb:
> btw: "void foo(void)" war schon in ur-C "falsch"/unnötig...

Wie kommst du denn darauf? In "ur-C" gab es noch gar kein void. Und 
später (bis heute) war es in C nicht zwingend nötig, aber durchaus 
anzuraten. Erst in C++ ist es wirklich unnötig (aber dennoch nicht 
falsch).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.