mikrocontroller.net

Forum: Compiler & IDEs undefined reference mit "extern inline" in header


Autor: kruemeltee (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich versuche gerade ezfb ( http://www.akrobiz.com/ezfb/ , eine 
Framebuffer-Lib) in  meinem eigenen Projekt zu compilieren, stosse da 
aber auf ein Problem.

Die Demos lassen sich ohne weiteres von meinem Host-GCC compilieren.
Der Cross-Compiler, der ezfb compilieren soll ist ein GCC für ARM.
Der compiliert auch ohne Warnungen mit -Wall durch, nur linken kann er 
nicht. Allerdings macht es keinen Unterschied ob ich den Host oder den 
Cross-Compiler im Makefile einsetze.

Hier die Fehlermeldungen:
...
ezfb_bmp.c:1205: undefined reference to `bmp_is_same_size'
ezfb_bmp.c:1733: undefined reference to `ezfb_get_g_from_rgb'
ezfb_bmp.c:1736: undefined reference to `ezfb_get_r_from_rgb'
ezfb_bmp.c:1760: undefined reference to `ezfb_get_b_from_rgb'
...
collect2: ld returned 1 exit status
...
Das sind noch ein paar mehr, aber alle Funktionen, die der Linker nicht 
findet sind in einer Header-Datei, die auch eingebunden wird.

Die Funktionen sehen da so aus:
extern inline u_short ezfb_get_r_from_rgb(struct ezfb* fb, u_int rgb)
{
    switch(fb->Var.bits_per_pixel)
    {
        default:
        case  1:
        case  2:
        case  4: return 0;
        //--------------------------------------------------------------------
        case  8: return (int)(255 * (rgb & 0xe0) / 224.0); // based on ezfb_set_cmap_reduction();
        //--------------------------------------------------------------------
        case 15:     // returns a scaled char ie: fb->Var.red.length bits to 8 bits
        case 16: {   // by adding the top msb's to the otherwise zeros at the low end
                      u_char c = (((rgb << EZFB_BITS_IN_CHAR) >> fb->colors.offset_plus_length_red) & fb->colors.bit_mask_red);
                      return c |= ((c & ~((1 << fb->Var.red.length) - 1)) >> fb->Var.red.length);
                 }   // off is off and full on is 255
        //--------------------------------------------------------------------
        case 24:
        case 32: return (rgb >> fb->Var.red.offset) & fb->colors.bit_mask_red;
    }
}
(Nur eine um zu sehen, wie genau die gemacht wurden.

Dass die in einer Header-Datei stehen, wundert mich ein wenig, aber die 
Demos compilieren ja auch ohne Fehler/Warnungen durch. Daher wird das 
schon seine Richtigkeit haben, oder?

Ich hoffe jemand von euch kann mir dabei helfen, das zu lösen :)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ersetze das 'extern' durch 'static'


(Da hat wieder mal jemand nicht begriffen, was inline eigentlich macht, 
bzw. darüber nachgedacht, was der Compiler da machen soll. Auch das 
Schlüsselwort 'extern' hat den Progammierer anscheinend verwirrt. Die 
Kombination 'extern inline' ist so ziemlich die unsinnigste Kombination, 
die man sich vorstellen kann)

Autor: kruemeltee (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das habe ich jetzt gemacht und der Linker findets auch. Allerdings:
warning: 'ezfb_get_b_from_rgb' is static but used in inline function 'ezfb_get_b_from_pixel' which is not static
Was heisst nun das? Ich glaube nicht, dass das auf Dauer so 
funktionieren wird, heisst nicht umsonst Warnung :D

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kruemeltee schrieb:

> is static but used in inline function 'ezfb_get_b_from_pixel'

'ezfb_get_b_from_pixel' ist selber wieder eine inline Funktion.
Schreib der auch noch ein static davor.

Autor: kruemeltee (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>'ezfb_get_b_from_pixel' ist selber wieder eine inline Funktion.
>Schreib der auch noch ein static davor.
Omg, danke... Da war doch was mit den vielen Bäumen vor dem Wald oder so 
;)

Ich dachte anhand der Meldung, dass sich die Funktionen umgekehrt herum 
aufrufen, konnte aber z.B. in der, die ich oben gepostet habe, das nicht 
finden. Darum war ich etwas sehr verwirrt.

Vielen Dank für deine Hilfe!

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bezüglich *extern inline*: Warum wird das überhaupt zugelassen? Inline 
verlangt doch, dass dem Compiler in der Compilation Unit der gesamte 
Funktionscode vorliegt. Extern hingegen sagt dem Compiler ja 
(gegensätzlich), dass es die Funktion gibt, nur dass er keinen Code zu 
sehen bekommt.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
extern inline stellt ihm laut C99 frei, welche der beiden Definitionen
(die beide vorliegen müssen) er dann benutzt.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch schrieb:
> extern inline stellt ihm laut C99 frei, welche der beiden Definitionen
> (die beide vorliegen müssen) er dann benutzt.

In dem Fall muss es dann aber auch irgendwo eine tatsächliche 
Implementierung geben. Offenbar gabs die aber in diesem Projekt nicht 
und der Compiler hat sich gegen das inlineing entschieden.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder kruemeltee hat vergessen die Library einzutragen im Makefile?

Autor: Pothead (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch schrieb:
> extern inline stellt ihm laut C99 frei, welche der beiden Definitionen
> (die beide vorliegen müssen) er dann benutzt.

Doll. Man lernt nie aus... Jörg, kannst du ein Minimalbeispiel 
konstruieren? So richtig sinnig scheint mir das nicht zu sein.

Autor: Pothead (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich versuchs mal selber...etwa so?

eins.c:
include "eins.h"

void baz(void)
{
   foo();  // "inlining"?
}

inline void 
foo(void)
{
}

eins.h:
extern inline void foo(void);

zwei.c:
#include "eins.h"

void
bar(void)
{
   foo();  // kein "inlining"?
}

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würd eher sagen so:


zwei.c
#include "zwei.h"

/* Nicht-geinlined */
int zwei(int A)
{
    return A*A;
}

zwei.h
/* Geinlined */
extern inline int zwei(int A)
{
    return A*A;
}

eins.c
#include "zwei.h"

void eins(void)
{
    /* Aufruf kann entweder geinlined oder gelinkt sein */
    zwei();
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.