Не наружная функция с C-связью
Можно ли объявить функцию с C-связью без наличия внешней привязки? При попытке скомпилировать
extern "C" static void f() {}
Я получаю
f.cc:1: error: invalid use of 'static' in linkage specification
что имеет смысл, в некотором роде. В namespace { extern "C" void f() {} }
спецификатор extern
, кажется, переопределяет ограниченную область анонимного пространства имен.
Если это невозможно, имеет значение при передаче указателя функции на C?
Ответы
Ответ 1
Вы можете сделать
extern "C" {
static void f() {}
}
Это даст функцию f
типа C, которая на практике означает, что она использует соглашение о вызове C на вашей платформе. Имя функции все равно будет иметь С++/внутреннюю связь, поскольку спецификация языкового связывания применима только к именам функций внешней связи.
Если вы укажете extern "C"
непосредственно в объявлении, стандарт указывает, что значение extern "C"
считается также спецификатором класса хранения, поэтому, если вы добавите static
, вы получите конфликт.
Имеет ли значение при передаче указателя функции на C
Теоретически это имеет значение - реализация может отличаться поведением от вызова функции, тип которой имеет связь С++ с вызовом функции, тип которой имеет C-связь. Однако я не знаю деталей реализации, а именно, что говорит об этом. Лучше следовать спецификации, и вы в безопасности.
Ответ 2
Вы можете передать указатель на функцию не-член или статическую функцию С++ в функцию C и должны работать, если вы не указали другое соглашение о вызове для этой функции С++. Регулярная функция С++ должна использовать соглашение о вызове C, чтобы вы были на этом фронте.
Основная причина, по которой передается указатель на нестационарную функцию-член, не работает так легко, потому что вам также нужно будет передавать информацию об указателе объекта this
, что обычно происходит как неявное, невидимый параметр для любой функции-члена.
Ответ 3
Я просто успешно использовал ответы Йоханнеса. Спасибо, чувак!
Так как я не могу (пока) комментировать, но могу ответить, позвольте мне просто добавить эту точку данных.
Я напечатал в <the-file>.cpp
(подробности милосердно опущены:-):
extern "C" {
extern int myfunction(<the-args>);
}
extern int myfunction(<the-args>) {
<the-code>
}
а также:
extern "C" {
static int myfunction(<the-args>);
}
static int my function(<the-args>) {
<the-code>
}
Я скомпилировал оба пути и сделал:
nm -g <the-file>.o | grep myfuncion
в двух объектных файлах по очереди.
Я заметил, что для extern это была запись, но для статического случая ее не было.
Итак, я достаточно доволен, что внешний "extern" просто устанавливает связь, а режим адресации статический для статического случая.