Forum: Mikrocontroller und Digitale Elektronik Verlinkungsproblem header


von pete (Gast)


Lesenswert?

Hallo Forum,


es geht bei mir um einen Verlinkungsfehler.

Ich habe im c-file (demmel.c) Funktionen geschrieben, die Funktionen aus 
einer anderen Header nehmen sollen.

Wenn ich in der c-Datei
1
#include <communication/I2C/TWI_Master/TWI_Master.h>

 einfüge, funktioniert es.

Die TWI_Master.h ist in dem Atmel Ordner vorhanden, sodass es mit "<>" 
klappt eigene Header Dateien einzubinden.

Ich habe jedoch eine weitere Header-Datei (demmel.h).
Wenn ich dort den include Befehl schreibe, dann gibt es den Fehler.

"Error  18  ld returned 1 exit status  collect2.exe  0  0  main".

In demmel.c ist auch "demmel.h" enthalten


Vielen Dank

Pete

P.S.

Sonst hat es immer so geklappt.

von pete (Gast)


Lesenswert?

so klappts nicht:

demmel.h:
1
#include <communication/I2C/TWI_Master/TWI_Master.h> // enthällt #include <avr/io.h>
2
3
4
uint8_t demmel_send_i2c_instruction(uint8_t demmel_address, uint8_t instruction);
5
6
uint8_t demmel_i2c_read_data_size(uint8_t demmel_address);
7
8
uint16_t demmel_i2c_read_info(uint8_t demmel_address);

demmel.c:
1
#include "demmel.h"
2
3
4
uint8_t demmel_send_i2c_instruction(uint8_t demmel_address, uint8_t instruction)
5
{
6
7
  if ( !TWI_M_start(demmel_address, WRITE, NO_OPTION) )
8
  {
9
    
10
    demmel_i2c_stop();
11
    return NO_SUCCESS;
12
13
  }
14
  // Output command CC_DATA_SIZE_READ
15
  if ( !TWI_M_write(instruction) )
16
  {
17
    
18
    demmel_i2c_stop();
19
    return SUCCESS;
20
    
21
  }
22
  
23
  return SUCCESS;
24
  
25
}

von pete (Gast)


Lesenswert?

so aber schon:

demmel.h:
1
#include <avr/io.h>
2
3
4
uint8_t demmel_send_i2c_instruction(uint8_t demmel_address, uint8_t instruction);
5
6
uint8_t demmel_i2c_read_data_size(uint8_t demmel_address);
7
8
uint16_t demmel_i2c_read_info(uint8_t demmel_address);


demmel.c:
1
#include "demmel.h"
2
3
#include <communication/I2C/TWI_Master/TWI_Master.h>
4
5
uint8_t demmel_send_i2c_instruction(uint8_t demmel_address, uint8_t instruction)
6
{
7
8
  if ( !TWI_M_start(demmel_address, WRITE, NO_OPTION) )
9
  {
10
    
11
    demmel_i2c_stop();
12
    return NO_SUCCESS;
13
14
  }
15
  // Output command CC_DATA_SIZE_READ
16
  if ( !TWI_M_write(instruction) )
17
  {
18
    
19
    demmel_i2c_stop();
20
    return SUCCESS;
21
    
22
  }
23
  
24
  return SUCCESS;
25
  
26
}



sind jetzt auch nur codeabschnitte. und das compilieren klappt so.

von Karl H. (kbuchegg)


Lesenswert?

pete schrieb:

> sind jetzt auch nur codeabschnitte. und das compilieren klappt so.

Die Fehlermeldung ist nicht vom Compiler, sondern vom Linker.
Bist du sicher, dass dir im Projekt nicht irgendein TWI Source Code File 
fehlt, in dem beim linken fehlende Funktionen drinnen sind?

von pete (Gast)


Lesenswert?

bei mir steht, dass eine multiple verlinkung stattfindet und das die 
funktionen shcon da sind

von pete (Gast)


Lesenswert?

Ich hab hier nochmal die Kopie:

Error  1  multiple definition of `TWI_M_init'  c:\program files 
(x86)\atmel\atmel toolchain\avr8 
gcc\native\3.4.1056\avr8-gnu-toolchain\avr\include\communication\i2c\twi 
_master/twi_master.h   102  1  main

von #define DEMMEL_H (Gast)


Lesenswert?

Was mir auf die Schnelle auffällt: Deine Header haben keinen Include 
Guard. Das kann dann leicht zu derartigen Problemen führen.

von pete (Gast)


Lesenswert?

Hab ich in der Header stehen von demmel.h, auch in der TWI_Master.h ist 
eins vorhanden (TWI_MASTER_H_).


#ifndef DEMMEL_H_
#define DEMMEL_H_

#endif

von Bitflüsterer (Gast)


Lesenswert?

Mag sein, es handelt sich um ein Mißverständnis. Das räume doch bitte 
einmal aus.

Ein "Include-Guard" besteht nicht nur darin ein #define davon abhängig 
zu machen, ob es schon existiert. Es muss auch das #include Statement 
selbst davon abhängig sein. Dein Code zeigt leider weder das eine noch 
das andere und Deine Antwort von 12:49 eben nur das #define.

Bei komplexen Projekten kann man sich schon mal in einem Wust von 
geplant strukturierter Dateiorganisation, includes und make Anweisungen 
verstricken. Das ist allen schon mal passiert. Aber fang doch bitte 
damit an, einfach mal die Fehlermeldung zu posten. Am besten sogar 
mehrere (falls das zutrifft). Vielleicht die ersten 5 oder so. Nicht 
uninteressant wäre auch die Ausgabe des Build-Prozesses. Am besten als 
Anhang, weil die vermutlich recht lang ausfällt.

von Karl H. (kbuchegg)


Lesenswert?

pete schrieb:
> Ich hab hier nochmal die Kopie:
>
> Error  1  multiple definition of `TWI_M_init'  c:\program files
> (x86)\atmel\atmel toolchain\avr8
> gcc\native\3.4.1056\avr8-gnu-toolchain\avr\include\communication\i2c\twi 
_master/twi_master.h
> 102  1  main

Das ist aber ein ganz anderes Problem.
Du hast ein Header File und in diesem Header File ist der Source Code 
für die Funktion TWI_M_init drinnen.

Und genau das macht man nicht.
Im Header File steht nur der Funktionsprotoyp! Die Implementierung kommt 
in ein C-File und dieses C-File wird zum Projekt hinzugefügt, damit es 
mitcompiliert und mitgelinkt wird.

twi_master.h
1
#ifndef TWI_MASTER_INCLUDED
2
#define TWI_MASTER_INCLUDED
3
4
void TWI_M_init( void );
5
... alle anderen Funktionen als Protoyp
6
7
#endif

twi_master.c
1
#include <avr/io.h>
2
#include "twi_master.h>
3
4
void TWI_M_init()
5
{
6
  .... hier der Code
7
}
8
9
... und ditto für alle anderen Funktionen

: Bearbeitet durch User
von Bitflüsterer (Gast)


Lesenswert?

Ups. Eine Fehlermeldung steht da ja schon. Sorry.

Was Du da hast, ist eine mehrfache Definition. D.h. in einem oder 
mehrere C-Files steht mindestens zweimal eine Funktionsdefinition. Ein 
Text, der eine Funktion zusammen mit dem Funktionsrumpf enthält. Alles 
andere ist eine Funktionsdeklaration, die dazu dient, dem Compiler 
Parameter und Rückgabewert einer später noch zu definierenden Funktion 
bekannt zu machen.

Die einfachste Methode, die ich verwende, ist eine Suche nach dem 
Funktionsnamen in allen Dateien. Das findet auch Deklarationen die man 
dem Augenschein nach noch von den Definitionen unterscheiden muss.

Viele IDEs bieten auch die Möglichkeit nach Definitionen zu suchen und 
lassen sich auch nicht von mehrfachen Definitionen abschrecken. 
Hilfreich finde ich auch Programme wie "sourcenav".

von Bitflüsterer (Gast)


Lesenswert?

OK. Damit habe ich nicht gerechnet. Karl Heinz hat natürlich Recht. Die 
Fehlermeldung weist auf eine in einem Header File befindliche 
zusätzliche Definition hin.

von pete (Gast)


Lesenswert?

naja, ich mach das auch immer so, die Funktionsköpfe in die Header und 
den Code ins c-file.

Jedoch wenn man es mit "<>" Klammern einbinden möchte und nicht immer 
die Dateien in den Ordner mitreinzukopieren und in den Explorer 
einzufügen, müssen es Header mit den Code sein.


Komischerweißse hat es immer so funktioniert, jetzt plötzlich nicht mehr

von Karl H. (kbuchegg)


Lesenswert?

pete schrieb:
> naja, ich mach das auch immer so, die Funktionsköpfe in die Header und
> den Code ins c-file.
>
> Jedoch wenn man es mit "<>" Klammern einbinden möchte und nicht immer
> die Dateien in den Ordner mitreinzukopieren und in den Explorer
> einzufügen,

reinkopieren musst du nichts.
Jede einigermassen vernünftige IDE hat kein Problem damit, wenn die 
Source Code Files auf mehreren Verzeichnissen 'verteilt' sind.

>  müssen es Header mit den Code sein.

du siehst ja, was dann dabei rauskommt.
Header im Code funktioniert im Einzelfall, wenn dein Projekt aus 
lediglich EINEM C-File besteht. Sobald du aber dein Projekt auf mehrere 
C-Files aufteilst und einige davon inkludieren denselben Header, dann 
kracht es eben.

Fazit: Wenn man es richtig macht, funktioniert es immer. Wenn man 
Krücken akzeptiert, darf man sich nicht wundern, wenn man auch mal auf 
die Schnauze fällt.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Header im Code funktioniert ...

Anders rum natürlich: Code im Header ....

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.