Только что дошло до моего сведения, что стандарт C ++ говорит, что функции C и C ++ имеют разные и несовместимые типы, даже если их сигнатуры типов одинаковы (для получения дополнительной информации см. этот вопрос). Это означает, что вам технически не разрешено передавать функцию C ++ функции C, например pthread_create()
,
Мне любопытно, существуют ли какие-либо платформы, в которых два ABI фактически различаются (кроме очевидных различий в названиях). В частности, кто-нибудь знает о каких-либо платформах, где эта программа C ++ не сможет скомпилироваться и запустить?
#include <assert.h>
extern "C" int run(int (*f)(int), int x) { return f(x); }
int times2(int x) { return x * 2; }
int main(int argc, char *argv[]) {
int a = times2(argc);
// This is undefined behavior according to C++ because I am passing an
// "extern C++" function pointer to an "extern C" function.
int b = run(×2, argc);
assert(a == b);
return a;
}
Я не знаю ни одной платформы, где ABI отличается, но даже если соглашения о вызовах C и C ++ одинаковы, стандарт C ++ требует, чтобы компилятор выдал диагностику для программы. Связь указатель на функцию с языком C отличается от типа указатель на функцию с C ++ — связь языка, поэтому вы должны иметь возможность перегружать run()
вот так:
extern "C" int run(int (*f)(int), int x) { return f(x); }
extern "C++" int run(int (*f)(int), int x) { return f(x); }
Теперь, когда вы звоните run(times)
он должен вызывать второй, поэтому из этого следует, что первый не может быть вызван (нет преобразования из указателя на функцию с языком C-языка в указатель на функцию с языком C ++ — language- linkage) и поэтому оригинальный код должен вызывать диагностику компилятора. Большинство компиляторов ошибаются, например, например. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=2316
Нотабене Компилятор Solaris делает диагностируйте несовместимые языковые связи, как предупреждение:
"t.c", line 11: Warning (Anachronism): Formal argument f of type extern "C" int(*)(int) in call to run(extern "C" int(*)(int), int) is being passed int(*)(int).
Если вы перегружены run
с extern "C++"
Функция правильно вызывает extern "C++"
один для run(times)
,
Других решений пока нет …