Syntax:
EXTERN { "C" | "C++" | "Windows" | "Windows-MS" } [ LIB "LibName" ]
' Deklarationen
END EXTERN
Typ: Anweisung
Kategorie: Bibliotheken
'EXTERN "Mangling"' startet einen Block, innerhalb dessen alle Deklarationen andere interne Bezeichner erhalten, als sie von FreeBASIC bekommen würden. Dies hat für den Programmfluss keine direkten Auswirkungen. Bei der Rückgabe von Fehlermeldungen oder beim Debuggen mittels externer Programme kann dies allerdings von Vorteil sein.
- EXTERN "C": setzt alle Prozeduren auf CDECL und erhält die Groß-/Kleinschreibung von allen Namen. Dasselbe Verhalten erreicht man ohne EXTERN durch die Aufrufkonvention CDECL zusammen mit einem ALIAS-String, der exakt denselben Prozedurnamen enthält.
- EXTERN "C++": wie EXTERN "C", stellt die Namen zusätzlich aber auf die Konventionen von g++-4.x
- EXTERN "Windows": setzt alle Prozeduren auf STDCALL, erhält die Groß-/Kleinschreibung von allen Namen und setzt zusätzlich das Suffix "@N" an alle Prozedurnamen, wobei N die Größe aller Parameter der jeweiligen Prozedur in Bytes ist.
- EXTERN "Windows-MS": wie EXTERN "Windows", nur dass das Suffix unter DOS/Windows nicht angehängt wird.
LIB "LibName" kann verwendet werden, um eine Lib einzubinden. Zusätzlich werden alle Prozedurdeklarationen innerhalb des Blocks so behandelt, als wäre bei der Deklaration ein 'LIB "LibName"' angegeben worden. Das kann aber durch explizite Angabe von LIB bei der Deklaration überschrieben werden.
Im EXTERN...END EXTERN-Block sind nur Deklarationen zulässig, sogenannte "ausführbare Anweisungen" dürfen innerhalb eines Blocks nicht auftreten. Im Detail sind die erlaubten Anweisungen:
Der Vorteil einer solchen Behandlung ist, dass der Linker einen leichter lesbaren Namen zurückgibt, wenn eine Referenz nicht gefunden werden konnte.
Als Block-Anweisung erstellt EXTERN einen eigenen SCOPE-Block.
Beispiel:
EXTERN "C++"
' Auch innerhalb des Namespace gilt die C++-Behandlung
NAMESPACE Ns1
DECLARE FUNCTION theFunction( BYVAL AS INTEGER ) AS UINTEGER
END NAMESPACE
END EXTERN
' Innerhalb dieses Namespace gilt die FreeBASIC-Behandlung
NAMESPACE Ns2
DECLARE FUNCTION theFunction( BYVAL AS INTEGER ) AS UINTEGER
END NAMESPACE
' Beide Funktionen existieren nicht; für beide wird also
' eine Fehlermeldung ausgegeben.
' Hier wird allerdings demonstriert, wie GNU C++ und
' FreeBASIC die Bezeichner intern handhaben; die
' Fehlermeldung EXTERN C++-Funktion ist wesentlich
' einfacher zu lesen:
Print Ns1.theFunction( 1 )
Print Ns2.theFunction( 1 )
Ausgabe:
Unter Windows erhält man in etwa folgende Fehlermeldung:
test.o:fake:(.text+0x54): undefined reference to `Ns1::theFunction(int)'
test.o:fake:(.text+0x68): undefined reference to `_ZN3NS211THEFUNCTIONEi@4
Dagegen sieht die Fehlermeldung unter Linux im zweiten Fall freundlicher aus:
test.o: In function `main':
(.text+0x23): undefined reference to `Ns1::theFunction(int)'
test.o: In function `main':
(.text+0x3a): undefined reference to `NS2::THEFUNCTION(int)'
Unterschiede zu QB: neu in FreeBASIC
Plattformbedingte Unterschiede:
Unter Linux hängt EXTERN "Windows" nie das Suffix "@N" an
Unterschiede zu früheren Versionen von FreeBASIC:
- Die Angabe "Windows-MS" existiert seit FreeBASIC v0.18.2
- EXTERN als Blockanweisung existiert seit FreeBASIC v0.16
Unterschiede unter den FB-Dialektformen: nur zulässig in der Dialektform -lang fb
Siehe auch:
EXTERN (Module), NAMESPACE, DECLARE, CDECL, STDCALL, Module (Library / DLL)