Я нахожу такие примеры в коде Повышения.
namespace boost {
namespace {
extern "C" void *thread_proxy(void *f)
{
....
}
} // anonymous
void thread::thread_start(...)
{
...
pthread_create(something,0,&thread_proxy,something_else);
...
}
} // boost
Почему Вам на самом деле нужно это extern "C"
?
Ясно что thread_proxy
функция частная внутренний, и я не ожидаю, что она была бы искажена как "thread_proxy", потому что мне на самом деле не нужен в искаженный вообще.
На самом деле во всем моем коде, который я написал и это работает на многих платформах, я никогда не использовал extern "C"
и это работало как есть с нормальными функциями.
Почему extern "C"
добавленный?
Моя проблема - это extern "C"
функции загрязняют глобальное пространство имен, и они не на самом деле скрыты, как автор ожидает.
Это не дубликат! Я не говорю об искажении и внешней связи. Очевидно в этом коде, что внешняя связь нежелательна!
Ответ: соглашения о вызовах C и функций C++ являются не обязательно тем же, таким образом, необходимо создать один с соглашением о вызовах C. См. 7.5 (p4) стандарта C++.
Ясно, что функция
thread_proxy
является частной внутренней, и я не ожидаю, что она будет изменена как «thread_proxy», потому что мне вообще не нужно ее искажать.
Тем не менее, он все равно будет поврежден. (Если бы не extern "C"
) Вот так работает компилятор. Я согласен с тем, что компилятор может сказать: «Это не обязательно должно быть искажено», но в стандарте об этом ничего не говорится. Тем не менее, искажение здесь не играет роли, поскольку мы не пытаемся связать с функцией.
Фактически, во всем моем коде, который я написал и который работает на многих платформах, я никогда не использовал
extern «C»
, и это работало как есть с обычными функциями.
Запись на разных платформах не имеет ничего общего с extern «C»
. Я ожидаю, что весь стандартный код C ++ будет работать на всех платформах, имеющих стандартный компилятор, совместимый с C ++.
extern «C»
имеет отношение к взаимодействию с C, библиотекой которого является pthread. Он не только не искажает имя, но и обеспечивает возможность вызова в соответствии с соглашением о вызовах C. Это соглашение о вызовах, которое должно быть гарантировано, и поскольку мы не можем предположить, что работаем на определенном компиляторе, платформе или архитектуре, лучший способ попробовать и сделать это - использовать предоставленные нам функции: extern «С»
.
Моя проблема в том, что функции
extern «C»
загрязняют глобальное пространство имен и на самом деле они не скрыты, как ожидал автор.
В приведенном выше коде нет ничего загрязняющего.Он находится в безымянном пространстве имен и недоступен за пределами единицы перевода.
Вопрос верен - хотя функция передается в библиотеку C, эта библиотека C вообще не связывается с кодом C ++. Ему дается только адрес функции, поэтому имя функции его не интересует.
Дело в том, что extern "C"
- это наиболее близкий к кроссплатформенному способу указания компилятору заставить функцию использовать стандартное соглашение о вызовах C на этой платформе (т.е. как именно параметры и возвращаемые значения должны быть переданы в стек).
К сожалению, это также имеет побочный эффект создания внешнего символа компоновщика на глобальном уровне. Но это можно смягчить, используя вместо этого имя вроде boost_detail_thread_proxy
.
Он используется для того, чтобы функция использовала то, что компилятор понимает согласно соглашению о вызовах C, избегая при этом специфичных для компилятора ключевых слов, таких как __ cdecl
.
Вот и все. Это не имеет абсолютно ничего общего с изменением имен, пространствами имен или любыми другими странными ответами здесь (как вы уже знали, когда спрашивали).
Вероятно, потому что вы взаимодействуете с простой библиотекой C - pthreads.
extern "C"
не обязательно означает, что подавляется только искажение имен. Фактически, может существовать компилятор, который обрабатывает extern «C»
как другое соглашение о вызовах.
Стандарт оставляет это полностью открытым как семантика, определяемая реализацией.