Глядя на комментарий, который вы поместили к предыдущему ответу («[M] y вопрос только в том, можем ли мы применить extern C
на уровне класса, чтобы все функции в классе автоматически имели искажение имени в стиле C?», Ответis 'extern "C"
не совсем так работает.'
Синтаксически, extern "C"
может применяться к одному выражению блока с разделенными фигурными скобками:
extern "C" int my_foo(int i)
{
...
}
extern "C" {
int my_bar(int i)
{
...
}
int my_baz(int i)
{
...
}
}
ЭтоОбычно используется extern "C"
с соответствующими #ifdef __cplusplus
защитными элементами для целых заголовков C.
Семантически фактический эффект применения extern "C"
будет применяться только к "нормальным" (то есть, неклассовым) функциям иуказатели на функции. Конечно, вы не можете применить его к шаблону C ++. Также вы не можете применить его к методам класса (потому что метод класса должен знать, к какому объекту он был вызван, а связь в стиле C не имеет никакого способа передачиэта информация в функции).
Это , возможно , можно применить extern "C"
к функциям, которые существуют в пространстве имен, но информация о пространстве имен просто исчезнетпри использовании через C.
Обновление
Если у вас уже есть класс (мы будем использовать POD class для простоты), и вы хотите сделатьЕго можно использовать из C, вам нужно применить extern "C"
к функции, вызываемой в C. К сожалению, это становится уродливым даже в простых случаях:
// in the header file
#ifdef __cplusplus
namespace X {
#endif
struct A
{
int x;
#ifdef __cplusplus
A() : x(5) { }
int foo()
{
return x += 5;
}
#endif
};
#ifdef __cplusplus
extern "C" {
#endif
int A_foo(struct A a);
struct A A_create();
#ifdef __cplusplus
}
}
#endif
// in the .cc file
#include "try.h"
namespace X {
extern "C" {
int A_foo(A* a)
{
return a.foo();
}
A A_create()
{
return A();
}
}
}
// in the .c file
#include <stdio.h>
#include "try.h"
int main()
{
struct A a = A_create();
printf("%d", A_foo(a));
}
Используя gcc, вы скомпилируете это следующим образом:
- файл C ++:
g++ try.cc -c -o try.o
- файл C:
gcc try.c try.o
Есть несколько важных моментов:
- Если ваш файл C ++ вызывает в STL за кулисами или вызывает
new
или delete
(или new[]
или delete[]
), вам нужно будет связать конечную программу с библиотекой времени выполнения C ++ (командная строкаПереключатель для этого в gcc: -lstdc++
. - Вы, вероятно, захотите передать идентичные флаги оптимизации при компиляции кода C и C ++ (оптимизация может повлиять на размер объектов и, если размерне соответствует, вы можете получить много неприятностей).То же самое для многопоточности.
- Вы можете использовать все исключения в коде C ++, но , когда они пересекают код C, все ставки отключены .
- Если вы хотите что-то большееСложно, вы, вероятно, захотите взглянуть на шаблон PIMPL.
- Когда структура выходит из области видимости в коде C, деструктор C ++ вызывается , а не (некоторые компиляторы могут обещать это сделать,но это не стандартно).Если вам нужно выполнить очистку этих объектов, вам нужно вызвать внешнюю функцию "C", которая вызывает деструктор.
Чтобы явно вызвать деструктор:
extern "C" void A_destroy(struct A a)
{
a.~A();
}