Probleme zwischen C++ und C Projekt Einbindung Funktion

(Firma: ---) #4197594
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
Angehängte Dateien:
Gast #4197618
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.
Gast #4197622
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
(Firma: ---) #4198028
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
#4198046
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.
(Firma: Wilhelm.Consulting) #4198048
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

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