Rozumiem, że kompilatory C ++ nie są ze sobą kompatybilne. Jednak nie byłem w stanie znaleźć niczego na ten temat, w szczególności dla C. Wiem, że standard C pozostawia wiele miejsca dla kompilatorów do implementacji rzeczy, które uznają za stosowne: na przykład rozmiar i wyrównanie większości (wszystkich?) Typów danych jest definiowane pod kątem implementacji, z pewnymi minimalnymi gwarancjami. Dlatego dwa kompilatory (lub dwie wersje tego samego kompilatora) mogą nie zgadzać się co do wielu szczegółów.
Czy mam rację, sądząc, że nie ma gwarancji, że dwa pliki obiektowe skompilowane z różnymi kompilatorami faktycznie się połączą? Na przykład rozmiar wskaźników może wynosić 32 bity w jednym pliku obiektowym i 64 bity w drugim. Ale jeśli tak, to dlaczego biblioteki C są czasami dystrybuowane we wstępnie skompilowanej formie? Czy jest oczekiwanie, że użyję tego samego kompilatora, którego używali (np. Gcc), lub jakiegoś faktycznego standardu, który zapewni zgodność binarną? I w jaki sposób inne języki z interfejsem języka obcego zapewniają prawidłowe wyrównanie podczas łączenia z plikami obiektów C?
Odpowiedzi:
Ogólna odpowiedź brzmi: nie, kompilatory w języku C nie są ze sobą kompatybilne. Standard języka C nie definiuje żadnej binarnej interoperacyjności, a większość autorów kompilatorów nawet nie próbuje.
Muszę to zakwalifikować. Obiekty emitowane przez kompilator C muszą być połączone z bibliotekami wykonawczymi, aby utworzyć bibliotekę wykonywalną lub bibliotekę wykonawczą. Chociaż funkcje widoczne w bibliotece wykonawczej C powinny być kompatybilne, pojawią się również funkcje niewidoczne, które są unikalne dla implementacji i zapobiegają interoperacyjności.
Ten brak zgodności dotyczy także różnych wersji tego samego kompilatora. Zasadniczo programów i bibliotek skompilowanych ze starszymi i nowszymi wersjami kompilatora nie można łączyć ze sobą, a tych skompilowanych z MSVC nie można połączyć z tymi skompilowanymi przez GCC.
Istnieje konkretny i bardzo przydatny wyjątek. Każda platforma zapewnia dynamiczne łączenie ABI (Application Binary Interface) i każdy program w dowolnym języku, który może być zgodny z tym ABI, jest kompatybilny. Dlatego generalnie możliwe jest zbudowanie biblioteki DLL (w systemie Windows) za pomocą MSVC (lub czegoś innego) i wywołanie jej z programu skompilowanego przez inną wersję MSVC lub przez GCC i odwrotnie.
Istnieją dwa inne ABI w systemie Windows: zespoły COM i .NET i obejmują one szeroki zakres języków. Więc interoperacyjność jest zdecydowanie możliwa, ale nie są kompatybilne.
Stopień niezgodności można łatwo sprawdzić, porównując mapy linkerów. Do użytku w GNU
ld -M
, do używania MSVClink /map
. Przeanalizuj dwa wygenerowane pliki. Oba będą zawierać nazwy, które rozpoznajesz, takie jak printf i main, chociaż (w zależności od opcji) nazwy mogą być zniekształcone na różne sposoby. Będą też mieć zupełnie inne nazwy, z których wielu nie rozpoznasz. Aby pliki obiektowe tworzone przez różne kompilatory były kompatybilne, muszą uzgodnić wszystkie te nazwy i nigdy tego nie robią. Nawet różne wersje tego samego kompilatora nie zawsze mogą to zrobić.źródło
To, czego szukasz, nazywa się ABI (Application Binary Interface).
Język C nie definiuje ABI, więc w tym sensie nie ma żadnej gwarancji, że pliki C skompilowane z różnymi kompilatorami będą ze sobą współpracować.
Z drugiej strony, na większości platform system operacyjny definiuje ABI do łączenia się z nim, a wszystkie kompilatory ukierunkowane na tę rodzinę systemów operacyjnych i rodziny procesorów również używają tego samego ABI do łączenia się ze składnikami innymi niż OS. W praktyce obiekty C utworzone przez różne kompilatory mogą ze sobą współpracować.
źródło