ich versuche ein bestehendes C-Project unter xcode auf dem MAC zu bauen. Der Compiler macht da aus irgendeinem Grund _ vor die Funktionsnamen und der Linker findet die dann nicht. Irgendwie hatte ich das schon Mal, es war irgendwas mit C und C++, habs aber vergessen wie man das umgeht. Also in einem file der AUfruf irgendwas(13); in einem anderen File die Definition: void irgendwas(int zahl) ... und er Linker verlangt dann nach _irgendwas
Kümmer Dich nicht um den _. Ist nur zur Vermeidung von gleichen Namen C/Assembler. Dem linker fehlt das (compilierte) File oder die lib, die die Funktion enthält. In C ohne _, im Assembler/Linker mit _.
:
Bearbeitet durch User
Walter S. schrieb: > Also in einem file der AUfruf > irgendwas(13); > > in einem anderen File die Definition: > void irgendwas(int zahl) ... > > und er Linker verlangt dann nach _irgendwas Willst Du von C++-Code aus bspw. C-Funktionen aufrufen? Dann hast Du es mit dem Name-Mangling des C++-Compilers zu tun. Das müsstest Du für die C-Funktionsdeklarationen mit
1 | extern "C" { |
2 | int CFunction(void); |
3 | }
|
ausschalten.
Wenn der Linker solch einen Symbolnamen nicht findet, wird dem Linker nicht die Objektdatei übergeben, in der das Symbol definiert ist. Oder das Symbol (hier: die Funktion "irgendwas") ist als static deklariert und ist daher nur innerhalb ihrer "translation unit" sichtbar. Da der Linker _irgendwas sucht, wird diese Funktion auch nicht aus C++-Code heraus aufgerufen, denn deren Signatur sähe durch das "name mangling" entschieden anders aus. Es könnte sein, daß die Funktion "irgendwas" aber als C++-Code übersetzt wurde, und daß der Aufrufer sie als C-Code aufrufen will, also genau andersherum als von Wilhelm beschrieben.
Das zusätzliche "leading underscore" in Symbolnamen wird von manchen ABIs vorgeschrieben, d.h. ein Symbolname hat 1 Underscore mehr als auf anderen Plattformen. So wird ein Object (Funktion oder Variable), das auf C-Ebene sym heißt, im Assembly als _sym ausgegeben. Beispiel C:
1 | int var; |
2 | |
3 | int fun (void) |
4 | {
|
5 | return var; |
6 | }
|
wird assembliert mit x686-w64-mingw32-gcc (unbedeutende Teile entfernt):
1 | .globl _fun |
2 | _fun: |
3 | movl _var, %eax |
4 | ret |
5 | |
6 | .globl _var |
7 | .bss |
8 | _var: |
9 | .space 4 |
Und das gilt dann auch für C++: fun wird in MinGW als __Z3funv assembliert, für x86_64-linux-gnu hingegen als _Z3funv. Was unter MinGW auffällt, ist dass Labels zum Beispiel "L5" heißen, was ohne Underscore dann mit einem Objekt namens "L5" verwechselt werden würde. Das ABI vermeidet dies, indem Symbole von Hochsprache einen "_" verpasst bekommen. Auf anderen Plattformen werden Labels z.B. als ".L5" benamt; keine Ahnung warum das unter Windows nicht gemacht wird / wurde. Evtl. kann ein Archäologe da mehr zu sagen. ------------------------------------------------------------ Um in einem Project C und C++ zusamme zu nutzen müssen die C-Teile als extern "C" Linkage implementiert sein, im obigen Beispiel etwa
1 | extern "C" int fun (void); |
Um Assembly und C/C++ zusammen zu verwenden, muss im Assembly die Naming Convention dem ABI folgen. Es ist zwar möglich, den Assembly Name mit GCC anzugeben, aber dabei wird man nach Möglichkeit dem ABI folgen, hier als GCC Erweiterung:
1 | int fun (void) __asm ("_bar"); |
Schließlich gibt es je nach Host noch -f[no-]leading-underscore, aber was ABI angeht gilt das eben gesagte.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.