Подтвердить что ты не робот

Внешняя связь "C" внутри пространства имен С++?

namespace someNameSpace {
    extern "C" void doSomething()
        {
             someOperations();
        }
}

Я хочу запустить doSomething() в среде С++ и C.

Является ли someNameSpace все еще инкапсулирующим doSomething(), если я выставляю его в ссылку extern "C"?

Есть ли хороший способ обмена функциями между С++ и C, избегая заражения глобального пространства имен на стороне С++?

Изменить. Поскольку этот код используется в основном в режиме С++, тогда как ссылка C используется только для тестирования, я думаю, что это лучший способ сделать это.

namespace someNameSpace {
    #ifdef COMPILE_FOR_C_LINKAGE
    extern "C"
    #else
    extern "C++"
    #endif
    { 
        void doSomething()
            {
                 someOperations();
            }
    }
}
4b9b3361

Ответ 1

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

См. 7.5/6:

Не более одной функции с определенным именем может иметь C-языковую связь. Две декларации для функции с привязкой языка C с тем же именем функции (игнорируя имена пространства имен, которые его квалифицируют), что отображаются в разных областях пространства имен, относятся к одной и той же функции. Две декларации для переменной с C языковая связь с тем же именем (игнорируя имена пространства имен, которые его квалифицируют), которые отображаются в разных области пространства имен относятся к одной и той же переменной. Субъект с C-языковой связью не должен быть объявлен с одно и то же имя как переменная в глобальной области видимости, если обе декларации не обозначают одну и ту же сущность; диагностика отсутствует требуется, если декларации появляются в разных единицах перевода. Переменная с C-языковой связью не должна быть объявлено с тем же именем, что и функция с привязкой языка C (игнорируя имена пространства имен, которые квалифицировать соответствующие имена); диагностика не требуется, если декларации появляются в другом переводе единицы. [Примечание. Только одно определение для объекта с заданным именем с привязкой к языку C может отображаться в программа (см. 3.2); это означает, что такой объект не должен определяться более чем в одном пространстве имен объем. - конечная нота]

Арбитры вашего корпоративного или глобального уровня проекта должны быть в состоянии дать вам рекомендации по подходящей политике именования для вашей базы кода.

Ответ 2

Просто кусок кода для иллюстрации поведения, изложенного в ответе Kerrek SB

#include <iostream>

namespace C{
    void Hello(){
        std::cout<<"Hello"<<std::endl;
    }
    extern "C" void HelloThere(){
        std::cout<<"Hello There from extern \"C\""<<std::endl;
    }
}

extern "C" void HelloThere();

int main() {
    C::Hello();
    C::HelloThere(); //Compiles
    //Hello(); <--- does not compile
    HelloThere(); //Also compiles and prints the same as C::HelloThere() !!!

    return 0;
}

Жить на http://ideone.com/X26wfR