Static linkage and extern "C"

Discussion in 'C++' started by Mark A. Gibbs, Oct 20, 2005.

  1. I have a question about mixing C and C++.

    In a C++ translation unit, I want to define a function with internal
    linkage and C calling convention. Here's a sample of what I want to do:

    // main.cpp

    // This is defined in a C module
    extern "C" void fake_qsort(void*, std::size_t, std::size_t,
    int (*compare)(const void*, const void*));

    namespace {

    int compare_func_(const void*, const void*);

    } // anonymous namespace

    int main()
    {
    foo bunch_of_foos[100];
    // ... fill bunch_of_foos somehow

    // Fake qsort has the same signature as std::qsort
    // but is extern "C"
    fake_qsort(&bunch_of_foos, sizeof(bunch_of_foos), sizeof(foo),
    compare_func_);

    return 0;
    }

    int compare_func_(const void*, const void*)
    {
    // ...
    }

    In a C++ translation unit, compare_func_() will have C++ calling
    convention by default, unless I explicitly declare it extern "C". And
    the fake_qsort() function is expecting a function with C calling convention.

    I know this is illegal:
    extern "C" static int compare_func_(const void*, const void*);

    And this *seems* to be legal:
    namespace {
    extern "C" int compare_func_(const void*, const void*);
    } // anonymous namespace

    But does it do what I want (give me a function with internal linkage but
    C calling convention)?

    What about this?
    extern "C" {
    static int compare_func_(const void*, const void*);
    }

    Or even this?
    extern "C" {
    namespace {
    int compare_func_(const void*, const void*);
    } // anonymous namespace
    }

    Mark
     
    Mark A. Gibbs, Oct 20, 2005
    #1
    1. Advertising

  2. "Mark A. Gibbs" <_x> wrote in message
    news:...
    >I have a question about mixing C and C++.
    >
    > In a C++ translation unit, I want to define a function with internal
    > linkage and C calling convention. Here's a sample of what I want to do:
    >
    > // main.cpp
    >
    > // This is defined in a C module
    > extern "C" void fake_qsort(void*, std::size_t, std::size_t,
    > int (*compare)(const void*, const void*));
    >

    .......
    > In a C++ translation unit, compare_func_() will have C++ calling
    > convention by default, unless I explicitly declare it extern "C". And the
    > fake_qsort() function is expecting a function with C calling convention.


    Don't bother with that. extern "C" does not really specify calling
    convention,
    (it might) but does not specify *which* C calling convention :) if more then
    one are available :)
    extern "C" is practically only usefull to tell compiler not to mangle
    symbols when
    exporting functions, but if you do need to specify calling
    convention you'll do it with implementation specific extensions anyway,
    in which case you don't need extern "C". You have to use it if compiler
    spits an error, which happens on some implementations.

    >
    > I know this is illegal:
    > extern "C" static int compare_func_(const void*, const void*);
    >
    > And this *seems* to be legal:
    > namespace {
    > extern "C" int compare_func_(const void*, const void*);
    > } // anonymous namespace
    >
    > But does it do what I want (give me a function with internal linkage but C
    > calling convention)?


    No. extern "C" function's can't be overloaded, neither namespace affects
    anything .You get exactly the same symbol with or without namespace.

    >
    > What about this?
    > extern "C" {
    > static int compare_func_(const void*, const void*);
    > }


    It's an error, logical if you want.
    >
    > Or even this?
    > extern "C" {
    > namespace {
    > int compare_func_(const void*, const void*);
    > } // anonymous namespace
    > }
    >


    Same thing . you want to export function name and to hide it in same time :)
    This simply shows that extern "C" wants to do two things with one blow,
    but fails both. :)
    You need specifier both for calling convention and for name mangling
    in real implementations.:)
    So just drop extern "C" and if it works, ok, let it be, and #ifdef
    implementations
    where that is forced. :)
    Final word, is that compiler might use different calling convention when
    calling C++ and different when calling C, in which case extern "C" does
    help, but that is nothing that can be fixed with switch or two :)

    Greetings, Bane.
     
    Branimir Maksimovic, Oct 20, 2005
    #2
    1. Advertising

  3. "Branimir Maksimovic" <> wrote in message
    news:dj74os$hbk$...
    >
    > Final word, is that compiler might use different calling convention when
    > calling C++ and different when calling C, in which case extern "C" does
    > help, but that is nothing that can be fixed with switch or two :)

    can't
     
    Branimir Maksimovic, Oct 20, 2005
    #3
  4. "Branimir Maksimovic" <> wrote in message
    news:dj74os$hbk$...
    >
    >> What about this?
    >> extern "C" {
    >> static int compare_func_(const void*, const void*);
    >> }

    >
    > It's an error, logical if you want.


    But not compiler error. It declares C function with internal linkage!

    Gosh, one learns something new every day.
     
    Branimir Maksimovic, Oct 20, 2005
    #4
  5. "Branimir Maksimovic" <> wrote in message
    news:dj798j$ji0$...
    >
    > "Branimir Maksimovic" <> wrote in message
    > news:dj74os$hbk$...
    >>
    >>> What about this?
    >>> extern "C" {
    >>> static int compare_func_(const void*, const void*);
    >>> }

    >>
    >> It's an error, logical if you want.

    >
    > But not compiler error. It declares C function with internal linkage!
    >
    > Gosh, one learns something new every day.


    So this is the case when
    namespace {
    void f();
    }

    can't replace:

    static void f();
     
    Branimir Maksimovic, Oct 20, 2005
    #5
  6. Mark A. Gibbs

    Greg Comeau Guest

    In article <dj79hq$jom$>,
    Branimir Maksimovic <> wrote:
    >"Branimir Maksimovic" <> wrote in message
    >news:dj798j$ji0$...
    >> "Branimir Maksimovic" <> wrote in message
    >> news:dj74os$hbk$...
    >>>> What about this?
    >>>> extern "C" {
    >>>> static int compare_func_(const void*, const void*);
    >>>> }
    >>>
    >>> It's an error, logical if you want.

    >>
    >> But not compiler error. It declares C function with internal linkage!
    >>
    >> Gosh, one learns something new every day.

    >
    >So this is the case when
    >namespace {
    >void f();
    >}
    >
    >can't replace:
    >
    >static void f();


    Say again?
    --
    Greg Comeau / Celebrating 20 years of Comeauity!
    Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
    World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
    Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
     
    Greg Comeau, Oct 20, 2005
    #6
  7. Branimir Maksimovic wrote:

    > Don't bother with that. extern "C" does not really specify calling
    > convention,
    > (it might) but does not specify *which* C calling convention :) if more then
    > one are available :)
    > extern "C" is practically only usefull to tell compiler not to mangle
    > symbols when
    > exporting functions, but if you do need to specify calling
    > convention you'll do it with implementation specific extensions anyway,
    > in which case you don't need extern "C". You have to use it if compiler
    > spits an error, which happens on some implementations.


    I'm a little confused. "Linkage-specification" does not mean the same
    thing as "calling convention"? Or is the linkage specification just a
    part of the calling convention (or is the calling convention just a part
    of the linkage specification)? The standard seems to tell me that a
    linkage-specification includes a calling convention (among other things,
    in 7.5.1).

    And if linkage specification is not the same as calling convention,
    doesn't that mean that for a given a compiler, the calling convention
    used for C and C++ must be the same (otherwise you couldn't mix C and
    C++ code)?

    And if the calling convention is the same for C and C++ functions, then
    why are these two function pointers different?

    extern "C" void (*pf_c)(void);
    extern "C++" void (*pf_cpp)(void);

    (If I'm reading the standard right, there is a difference between the
    two, and name mangling doesn't matter to function pointers.)

    >>I know this is illegal:
    >>extern "C" static int compare_func_(const void*, const void*);
    >>
    >>And this *seems* to be legal:
    >>namespace {
    >> extern "C" int compare_func_(const void*, const void*);
    >>} // anonymous namespace
    >>
    >>But does it do what I want (give me a function with internal linkage but C
    >>calling convention)?

    >
    >
    > No. extern "C" function's can't be overloaded, neither namespace affects
    > anything .You get exactly the same symbol with or without namespace.


    I don't see what that has to do with overloading functions. And I don't
    see what you're saying about getting the same symbol with or without the
    namespace.

    The way I see it is that this...

    void foo()
    {
    }

    .... defines a function that is externally visible with C++ linkage (when
    compiled in C++). This...

    namespace {
    void foo()
    {
    }
    } // anonymous namespace

    .... defines a function that is not externally visible with C++ linkage.
    This...

    extern "C" void foo()
    {
    }

    .... defines a function that is externally visible with C linkage. So
    logically, this...

    namespace {
    extern "C" void foo()
    {
    }
    } // anonymous namespace

    .... should define a function that is not externally visible with C
    linkage. No?

    > Same thing . you want to export function name and to hide it in same time :)
    > This simply shows that extern "C" wants to do two things with one blow,
    > but fails both. :)


    'extern "C"' doesn't necessarily export the function (if I'm reading
    this right). It would get exported anyway by default. 'extern
    "anything"' tells the compiler/linker the calling convention (for
    functions), and the format for the names of variables or functions with
    external linkage, among other things. To me that implies that you should
    be able to create 'extern "anything"' with *internal* linkage. It's
    functionally the same thing as something with external linkage, except
    the symbols aren't externally visible.

    > You need specifier both for calling convention and for name mangling
    > in real implementations.:)
    > So just drop extern "C" and if it works, ok, let it be, and #ifdef
    > implementations
    > where that is forced. :)
    > Final word, is that compiler might use different calling convention when
    > calling C++ and different when calling C, in which case extern "C" does
    > help, but that is nothing that can be fixed with switch or two :)


    So... there is no difference between 'extern "C"' and 'extern "C++"' for
    calling conventions, but there might be. And I don't need the 'extern
    "C"' linkage specifier, but I might. And if I do, I really don't,
    because I can use compiler settings to make it all go away.

    All that sounds a little evasive and silly. Either it's necessary or
    it's not, and if it is, then the question is still how to do it. If it
    makes no difference on most implementations, great, but if I can write
    one set of code that works (or at least that's legal C++, then we can
    deal with broken compilers), without having to use conditional
    compilation, then that seems to be the way to go.

    Mark
     
    Mark A. Gibbs, Oct 20, 2005
    #7
  8. Mark A. Gibbs wrote:
    > Branimir Maksimovic wrote:
    >
    > > Don't bother with that. extern "C" does not really specify calling
    > > convention,
    > > (it might) but does not specify *which* C calling convention :) if more then
    > > one are available :)
    > > extern "C" is practically only usefull to tell compiler not to mangle
    > > symbols when
    > > exporting functions, but if you do need to specify calling
    > > convention you'll do it with implementation specific extensions anyway,
    > > in which case you don't need extern "C". You have to use it if compiler
    > > spits an error, which happens on some implementations.

    >
    > I'm a little confused. "Linkage-specification" does not mean the same
    > thing as "calling convention"?


    No. calling convention is part of linkage specification.

    Or is the linkage specification just a
    > part of the calling convention (or is the calling convention just a part
    > of the linkage specification)?


    The opposite.

    The standard seems to tell me that a
    > linkage-specification includes a calling convention (among other things,
    > in 7.5.1).


    Yes.

    >
    > And if linkage specification is not the same as calling convention,
    > doesn't that mean that for a given a compiler, the calling convention
    > used for C and C++ must be the same (otherwise you couldn't mix C and
    > C++ code)?


    No. calling convention should be there in linkage specification.
    Problem is that extern "C" assumes only one possible calling
    convention.It is simply not descriptive enough.

    >
    > (If I'm reading the standard right, there is a difference between the
    > two, and name mangling doesn't matter to function pointers.)
    >
    > >>I know this is illegal:
    > >>extern "C" static int compare_func_(const void*, const void*);
    > >>
    > >>And this *seems* to be legal:
    > >>namespace {
    > >> extern "C" int compare_func_(const void*, const void*);
    > >>} // anonymous namespace
    > >>
    > >>But does it do what I want (give me a function with internal linkage but C
    > >>calling convention)?

    > >
    > >
    > > No. extern "C" function's can't be overloaded, neither namespace affects
    > > anything .You get exactly the same symbol with or without namespace.

    >
    > I don't see what that has to do with overloading functions.


    Overloaded funcions have different symbols.

    And I don't
    > see what you're saying about getting the same symbol with or without the
    > namespace.


    well, linker searches for symbols in object files.
    if you write namespace One{ void f(){} } namespace Two { void f(){} }
    you get two different functions.
    but
    namespace One { extern "C" void f(){} }
    namespace Two { extern "C" void f(){} }
    refer to same function "f" and you'll get same symbol for both
    of them which produces linker error.
    So namespaces does not affect extern "C" at all.

    >
    > The way I see it is that this...
    >
    > void foo()
    > {
    > }
    >
    > ... defines a function that is externally visible with C++ linkage (when
    > compiled in C++). This...
    >
    > namespace {
    > void foo()
    > {
    > }
    > } // anonymous namespace
    >
    > ... defines a function that is not externally visible with C++ linkage.


    No. it defines foo with external linkage. anonymous namespace simply
    generates unique identifier , which is unkown.
    you need "static" to specify internal linkage.

    > This...
    >
    > extern "C" void foo()
    > {
    > }
    >
    > ... defines a function that is externally visible with C linkage. So
    > logically, this...
    >
    > namespace {
    > extern "C" void foo()
    > {
    > }
    > } // anonymous namespace
    >
    > ... should define a function that is not externally visible with C
    > linkage. No?


    No. namespaces does not affect linkage nor extern "C" symbols.

    >
    > > Same thing . you want to export function name and to hide it in same time :)
    > > This simply shows that extern "C" wants to do two things with one blow,
    > > but fails both. :)

    >
    > 'extern "C"' doesn't necessarily export the function (if I'm reading
    > this right). It would get exported anyway by default. 'extern
    > "anything"' tells the compiler/linker the calling convention (for
    > functions), and the format for the names of variables or functions with
    > external linkage, among other things.


    No only two defined things are extern "C" for C linkage
    and extern "C++" for C++ linkage, other literals can be
    anything to implementation.

    To me that implies that you should
    > be able to create 'extern "anything"' with *internal* linkage.


    Problem is that that keyword "extern " is used to specify external
    linkage. Therefore you need extern "C" { static void f(); }
    to specify internal linkage.

    It's
    > functionally the same thing as something with external linkage, except
    > the symbols aren't externally visible.


    Or there are non of them. function with internal linkage does not need
    symbol at all.

    >
    > > You need specifier both for calling convention and for name mangling
    > > in real implementations.:)
    > > So just drop extern "C" and if it works, ok, let it be, and #ifdef
    > > implementations
    > > where that is forced. :)
    > > Final word, is that compiler might use different calling convention when
    > > calling C++ and different when calling C, in which case extern "C" does
    > > help, but that is nothing that can be fixed with switch or two :)

    >
    > So... there is no difference between 'extern "C"' and 'extern "C++"' for
    > calling conventions, but there might be. And I don't need the 'extern
    > "C"' linkage specifier, but I might. And if I do, I really don't,
    > because I can use compiler settings to make it all go away.
    >
    > All that sounds a little evasive and silly. Either it's necessary or
    > it's not, and if it is, then the question is still how to do it. If it
    > makes no difference on most implementations, great, but if I can write
    > one set of code that works (or at least that's legal C++, then we can
    > deal with broken compilers), without having to use conditional
    > compilation, then that seems to be the way to go.


    Problem is that extern "C" is not guaranteed too work even if
    compiles and links ok. You must know which calling convention
    library you call(or calling code) use.
    And if compiler does not use *that* calling convention
    even if you specify extern "C", then you have to do non portable
    stuff anyway.
    I didn;t saw any compiler that use something like
    extern "mangle_this_way_and_call_that_way_thing",
    ,rather, extern "C" is used to declare/define C function
    within C++ code.
    Strange enough it is not defined how to specify linking
    with other C++ compiler, but it is assumed you can link with
    C compiler :)

    Greetings, Bane.
     
    Branimir Maksimovic, Oct 20, 2005
    #8
  9. Branimir Maksimovic wrote:

    > Problem is that that keyword "extern " is used to specify external
    > linkage. Therefore you need extern "C" { static void f(); }
    > to specify internal linkage.


    I thought you said that was illegal. If it's legal, and if it creates a
    static extern "C" function, then that's what I need. Is that legal, and
    is that what it's supposed to do?

    Mark
     
    Mark A. Gibbs, Oct 20, 2005
    #9
  10. Mark A. Gibbs wrote:
    > Branimir Maksimovic wrote:
    >
    > > Problem is that that keyword "extern " is used to specify external
    > > linkage. Therefore you need extern "C" { static void f(); }
    > > to specify internal linkage.

    >
    > I thought you said that was illegal.


    Oh, I corrected that in follow up post to myself :)

    If it's legal, and if it creates a
    > static extern "C" function, then that's what I need.


    Yes.

    Is that legal, and
    > is that what it's supposed to do?


    Of course, yes.

    Greetings, Bane.
     
    Branimir Maksimovic, Oct 20, 2005
    #10
  11. Excellent! Thank you!

    Mark
     
    Mark A. Gibbs, Oct 21, 2005
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. usr2003
    Replies:
    4
    Views:
    632
    usr2003
    Sep 19, 2003
  2. Steve Kobes

    extern and linkage

    Steve Kobes, Jun 9, 2004, in forum: C Programming
    Replies:
    1
    Views:
    307
    Chris Torek
    Jun 9, 2004
  3. Ian
    Replies:
    22
    Views:
    1,017
  4. mimi
    Replies:
    4
    Views:
    454
  5. Replies:
    1
    Views:
    609
    Michael DOUBEZ
    Sep 12, 2008
Loading...

Share This Page