MyTetra Share
Делитесь знаниями!
Совместимость объектных файлов Си и Си++: name mangling и extern "C"
Время создания: 09.07.2024 17:23
Автор: xintrea
Текстовые метки: язык, C, СИ, C++, Си++, имя, функция, метод, mangling, манглинг, декодирование, extern, объектный, файл, объектник, _Z, префикс
Раздел: Компьютер - Программирование - Язык C++ (Си++)
Запись: xintrea/mytetra_syncro/master/base/1720535036qm57mwjn05/text.html на raw.github.com

В языке Си++, при компиляции исходного кода в объектный *.o-файл, происходит так называемый name mangling. В русскоязычной литературе этот процесс называется "декодирование имен".


Суть в том, что из-за возможности перегрузки имен функций (когда в языке в одном пространстве имен допустимо существование функций с одинаковыми именами но разными типами аргументов), в Си++ возникает проблема записи таких пересекающихся имен функций в объектнике. Чтобы ее решить, был придуман следующий механизм переименования функций, именуемый манглингом:



  • В начале имени функции пишется префикс "_Z". Он говорит о том, что это имя прошло через процедуру name mangling.
  • Далее указывается десятичное число, которое означает длину оригинального названия функции в символах.
  • Далее пишется само оригинальное имя функции.
  • Далее пристыковываются символы, обозначающие типы всех аргументов функции, слева-направо.



Вот пример.


Функция имеет прототип:



double summ(double x, int y)



Тогда после процедуры манглинга, функция будет называться:



_Z4summdi



Здесь:


  • "_Z" - это mangle-префикс,
  • "4" - длинна оригинального имени,
  • "summ" - само оригинальное имя,
  • "d" - тип double первого аргумента,
  • "i" - тип int второго аргумента.


Кстати, в языке Си такой проблемы нет - там нет перегрузки функций, и поэтому имя функции просто хранится "как есть". И в этом кроется проблема: невозможно просто так взять, и использовать объектник и заголовок от библиотеки Си в проекте на Cи++. Потому что при обращении к любой функции, в том числе и к функции summ(), компилятор Си++ будет производить name mangling. И естественно, при линковке программы, измененное манглингом имя просто не будет найдено в Си-шном объектнике.


Для того, чтобы в Си++ можно было вызвать функцию из объектника, написанного и скомпилированного на языке Си, используется конструкция extern "C". Пишется она так:



extern "C"

{

double summ(double x, int y)

}



Все функции, прототипы которых написаны внутри блока extern "C", будут вызываеться без использования name mangling.


Иногда имеет смысл заключать в extern "C" не просто прототипы функций, а само подключение заголовочного файла, который идет вместе с Си-шным объектником. Делается это так:



extern "C"

{

#include "our_math.h"

}



Тогда все прототипы, написанные внутри файла-заголовка, будут линковаться без использования name mangling.


Иногда авторы Си-шных библиотек учитывают, что их библиотека может использоваться как в составе Си-шного проекта, так и в составие Си++ кода. Для этого они в заголовочном файле сами пишут директиву extern "C", обрамляя ее конструкциями условной компиляции:



#ifdef __cplusplus

extern "C"

{

#endif


double summ(double x, int y)


#ifdef __cplusplus

}

#endif



В этом случае, в Си++ коде использовать конструкцию extern "C" не имеет смысла, линковка будет работать и без нее.


Так же в этом разделе:
 
MyTetra Share v.0.64
Яндекс индекс цитирования