source

C++ 네임스페이스 안에 외부 "C" 링크가 있습니까?

lovecheck 2023. 10. 14. 10:20
반응형

C++ 네임스페이스 안에 외부 "C" 링크가 있습니까?

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

뛰고싶습니다doSomething()C++ 및 C 환경 모두에서 사용할 수 있습니다.

이스someNameSpace여전히 캡슐화 중인doSomething()그것을 들춰보면extern "C"연계?

C++ 쪽의 글로벌 네임스페이스를 오염시키지 않으면서 C++와 C 사이에 기능을 공유할 수 있는 좋은 방법이 있습니까?

편집: 이 코드는 주로 C++ 모드에서 사용되지만 C 링크는 테스트용으로만 사용되기 때문에 이것이 더 좋은 방법이라고 생각합니다.

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

당신의 코드는 작동하지만 당신은 모든 기능이extern "C"링크는 이름의 같은 공간을 공유하지만, 이는 "이름 공간"의 C++ 개념과 혼동되지 않습니다.당신의 기능은 정말.someNameSpace::doSomething, 하지만 당신은 다른 것을 가질 수 없습니다.extern "C"이름을 지정하지 않은 함수doSomething다른 네임스페이스에도 적용할 수 있습니다.

7.5/6 참조:

특정 이름을 가진 최대 하나의 함수는 C 언어 연결을 가질 수 있습니다.서로 다른 네임스페이스 범위에 나타나는 동일한 함수 이름(자격을 부여하는 네임스페이스 이름 무시)을 가진 C 언어 링크가 있는 함수에 대한 두 개의 선언은 동일한 함수를 참조합니다.서로 다른 네임스페이스 범위에 나타나는 이름이 같은 C 언어 연결을 가진 변수(자격을 부여하는 네임스페이스 이름 무시)에 대한 두 가지 선언에서 동일한 변수를 참조합니다.C 언어 연결을 가진 개체는 두 선언이 동일한 개체를 나타내는 경우가 아니라면 전역 범위의 변수와 동일한 이름으로 선언되어서는 안 됩니다. 선언이 다른 번역 단위로 나타나는 경우 진단이 필요하지 않습니다.C 언어 연결이 있는 변수는 C 언어 연결이 있는 함수와 동일한 이름으로 선언되어서는 안 되며(각 이름에 적합한 네임스페이스 이름은 무시), 선언이 다른 번역 단위로 나타나는 경우 진단이 필요하지 않습니다.[참고:C 언어 연결이 있는 지정된 이름을 가진 엔티티에 대한 정의는 프로그램에 하나만 표시될 수 있습니다(3.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 에서 라이브로 만나보세요.

C++ ABI에서는 네임스페이스를 망글링해야 합니다.그래서 이것은:

namespace foo
{
    void bar(int){}
}

는 이러한 기호로 다소 번역됩니다.

foo::bar(int)

컴파일러가 비슷한 기호인 CABI를 사용하도록 강요할 때

namespace foo
{
    extern "C" void bazz(int){}
}

컴파일 후 다음과 같이 나타납니다.

bazz

godbolt: https://godbolt.org/z/BmVpSQ 에서 차이를 확인할 수 있습니다.

CABI에는 함수와 함께 망치는 네임스페이스나 인수 목록이 없으므로 전체 코드에서 이러한 기호를 1개만 가질 수 있습니다.두 번 정의:

namespace foo
{
    extern "C" void bazz(int){}
}

namespace foo2
{
    extern "C" void bazz(int){}
}

int main()
{
    foo2::bazz(5);
    return 0;
}

불법입니다클랑 컴파일러는 다음과 같은 경우 단순한 컴파일 오류를 발생시킵니다.

https://wandbox.org/permlink/r5CUXm7OKePtG35L

gcc 컴파일러도 오류를 발생시키지만 훨씬 더 신비로워 보입니다.

https://wandbox.org/permlink/BiN0auna9klBg5GE

언급URL : https://stackoverflow.com/questions/28996944/extern-c-linkage-inside-c-namespace

반응형