why can't a template function have extern "C" linkage?

Discussion in 'C++' started by Ian, Jul 27, 2005.

  1. Ian

    Ian Guest

    The title says it all.

    I can see the case where a function is to be called directly from C, the
    name mangling will stuff this up.

    But I can't see a reason why a template function can't be given extern
    "C" linkage where it is to be assigned to a C function pointer.

    Ian
     
    Ian, Jul 27, 2005
    #1
    1. Advertising

  2. Ian

    Andre Kostur Guest

    Ian <> wrote in news:1122500290.491907@drone2-svc-
    skyt.qsi.net.nz:

    > The title says it all.
    >
    > I can see the case where a function is to be called directly from C, the
    > name mangling will stuff this up.
    >
    > But I can't see a reason why a template function can't be given extern
    > "C" linkage where it is to be assigned to a C function pointer.
    >
    > Ian


    Um... how would your C program (which doesn't know anything about
    templates) include the header file where the template function is declared?
    Keep in mind that a template function doesn't actually exist until it is
    instantiated.... (not sure that "instantiated" is the right word....)
     
    Andre Kostur, Jul 27, 2005
    #2
    1. Advertising

  3. Andre Kostur wrote:
    > [..]
    > Keep in mind that a template function doesn't actually exist until it is
    > instantiated.... (not sure that "instantiated" is the right word....)


    It is the right word.

    V
     
    Victor Bazarov, Jul 27, 2005
    #3
  4. Ian

    Ian Guest

    Andre Kostur wrote:
    > Ian <> wrote in news:1122500290.491907@drone2-svc-
    > skyt.qsi.net.nz:
    >
    >
    >>The title says it all.
    >>
    >>I can see the case where a function is to be called directly from C, the
    >>name mangling will stuff this up.
    >>
    >>But I can't see a reason why a template function can't be given extern
    >>"C" linkage where it is to be assigned to a C function pointer.
    >>
    >>Ian

    >
    >
    > Um... how would your C program (which doesn't know anything about
    > templates) include the header file where the template function is declared?
    > Keep in mind that a template function doesn't actually exist until it is
    > instantiated.... (not sure that "instantiated" is the right word....)


    As I said, I understand why this case can't be, but the problem I had
    involved setting up some callbacks for a C driver. The driver API has a
    number of structs with function pointers for various callbacks.

    So in this case, the C function pointers will be assigned in C++ code,
    after the templates have been instantiated. the names are irrelevant to
    the C code.

    Ian
     
    Ian, Jul 28, 2005
    #4
  5. Ian

    Jay Nabonne Guest

    On Thu, 28 Jul 2005 11:08:17 +1200, Ian wrote:

    > As I said, I understand why this case can't be, but the problem I had
    > involved setting up some callbacks for a C driver. The driver API has a
    > number of structs with function pointers for various callbacks.
    >
    > So in this case, the C function pointers will be assigned in C++ code,
    > after the templates have been instantiated. the names are irrelevant to
    > the C code.
    >


    What problem are you running into? I'm not sure of your distinction of "C"
    vs. "C++" functions, unless you mean stand-alone vs. class member
    functions. Is your template creating a template function or a templated
    class? If it's a class, then you can't use the address of the member
    functions whether it's a template or not.

    As far as I know, 'extern "C"' is irrelevant as far as function
    pointers go.

    If all else fails, create a standalone (non-template) function that calls
    the template one, and set a pointer to it instead.

    - Jay
     
    Jay Nabonne, Jul 28, 2005
    #5
  6. Ian

    Ian Guest

    Jay Nabonne wrote:
    > On Thu, 28 Jul 2005 11:08:17 +1200, Ian wrote:
    >
    >
    >>As I said, I understand why this case can't be, but the problem I had
    >>involved setting up some callbacks for a C driver. The driver API has a
    >> number of structs with function pointers for various callbacks.
    >>
    >>So in this case, the C function pointers will be assigned in C++ code,
    >>after the templates have been instantiated. the names are irrelevant to
    >>the C code.
    >>

    >
    >
    > What problem are you running into? I'm not sure of your distinction of "C"
    > vs. "C++" functions, unless you mean stand-alone vs. class member
    > functions. Is your template creating a template function or a templated
    > class? If it's a class, then you can't use the address of the member
    > functions whether it's a template or not.
    >

    In an ideal world, I wanted something like:

    extern "C" {
    template <typename T> int bla() { return T().bla(); }
    }

    so I could set up the C struct thus:

    template <typename T>
    struct Fred : FredFromC
    {
    Fred() { fnPointer = bla<T>; }
    };

    Where fnPointer is a member of FredFromC.

    > As far as I know, 'extern "C"' is irrelevant as far as function
    > pointers go.
    >

    That's just it, there is a difference and it is relevant.

    Ian
     
    Ian, Jul 28, 2005
    #6
  7. Ian

    Jay Nabonne Guest

    On Thu, 28 Jul 2005 11:47:09 +1200, Ian wrote:

    > In an ideal world, I wanted something like:
    >
    > extern "C" {
    > template <typename T> int bla() { return T().bla(); }
    > }
    >
    > so I could set up the C struct thus:
    >
    > template <typename T>
    > struct Fred : FredFromC
    > {
    > Fred() { fnPointer = bla<T>; }
    > };
    >
    > Where fnPointer is a member of FredFromC.
    >


    This compiles for me under Visual C++ 7.0 and gcc 3.2.3:

    // Begin code
    struct FredFromC
    {
    int (*fnPointer)();
    };

    template <typename T> int bla() { /*return T().bla();*/ return 0; }

    template <typename T>
    struct Fred : FredFromC
    {
    Fred() { fnPointer = bla<T>; }
    };

    Fred<int> myStruct;

    // End code

    It even works if I put 'extern "C"' around the "FredFromC" structure
    definition.

    Again, what is the problem that you're having (e.g. what is the error
    message).

    - Jay
     
    Jay Nabonne, Jul 28, 2005
    #7
  8. Ian wrote:
    > In an ideal world, I wanted something like:
    >
    > extern "C" {
    > template <typename T> int bla() { return T().bla(); }
    > }
    >
    > so I could set up the C struct thus:
    >
    > template <typename T>
    > struct Fred : FredFromC
    > {
    > Fred() { fnPointer = bla<T>; }
    > };
    >
    > Where fnPointer is a member of FredFromC.


    And how is it going to be used?

    V
     
    Victor Bazarov, Jul 28, 2005
    #8
  9. Ian

    Ian Guest

    Victor Bazarov wrote:
    > Ian wrote:
    >
    >>In an ideal world, I wanted something like:
    >>
    >>extern "C" {
    >> template <typename T> int bla() { return T().bla(); }
    >>}
    >>
    >>so I could set up the C struct thus:
    >>
    >>template <typename T>
    >>struct Fred : FredFromC
    >>{
    >> Fred() { fnPointer = bla<T>; }
    >>};
    >>
    >>Where fnPointer is a member of FredFromC.

    >
    >
    > And how is it going to be used?
    >

    By the operating system as a callback into the driver. FredFromC is a
    structure defined by the OS to be populated with callbacks for various
    driver functions.

    Ian
     
    Ian, Jul 28, 2005
    #9
  10. Ian

    Ian Guest

    Jay Nabonne wrote:
    > On Thu, 28 Jul 2005 11:47:09 +1200, Ian wrote:
    >
    >
    >>In an ideal world, I wanted something like:
    >>
    >>extern "C" {
    >> template <typename T> int bla() { return T().bla(); }
    >>}
    >>
    >>so I could set up the C struct thus:
    >>
    >>template <typename T>
    >>struct Fred : FredFromC
    >>{
    >> Fred() { fnPointer = bla<T>; }
    >>};
    >>
    >>Where fnPointer is a member of FredFromC.
    >>


    >
    > Again, what is the problem that you're having (e.g. what is the error
    > message).
    >

    If I compile the following (based on your example):

    extern "C" {
    struct FredFromC
    {
    int (*fnPointer)();
    };
    }

    template <typename T> int bla() { return 0; }

    template <typename T>
    struct Fred : FredFromC
    {
    Fred() { fnPointer = bla<T>; }
    };

    int
    main()
    {
    Fred<int> myStruct;
    }

    The compiler correctly warns:

    "/tmp/x.cc", line 13: Warning (Anachronism): Assigning int(*)() to
    extern "C" int(*)().

    In this example, I can see no practical reason why bla() couldn't have
    been declared as extern "C".

    Ian
     
    Ian, Jul 28, 2005
    #10
  11. Ian

    Jay Nabonne Guest

    On Thu, 28 Jul 2005 12:38:08 +1200, Ian wrote:

    >
    > The compiler correctly warns:
    >
    > "/tmp/x.cc", line 13: Warning (Anachronism): Assigning int(*)() to
    > extern "C" int(*)().
    >
    > In this example, I can see no practical reason why bla() couldn't have
    > been declared as extern "C".
    >


    Ah, I see. A warning. Unfortunately, I can't coax any of the compilers I
    have at my disposal to warn me about that, so I can't even begin to try to
    figure out how to solve it (as I have no way to test).

    I suppose this does no better:

    template <typename T>
    struct Fred : FredFromC
    {
    static int bla() { /*return T().bla();*/ return 0; }
    Fred() { fnPointer = bla<T>; }
    };

    Good luck...

    - Jay
     
    Jay Nabonne, Jul 28, 2005
    #11
  12. Ian

    Jay Nabonne Guest

    On Thu, 28 Jul 2005 00:49:45 +0000, Jay Nabonne wrote:

    > On Thu, 28 Jul 2005 12:38:08 +1200, Ian wrote:
    >
    > template <typename T>
    > struct Fred : FredFromC
    > {
    > static int bla() { /*return T().bla();*/ return 0; }
    > Fred() { fnPointer = bla<T>; }


    // Oops. I meant:

    Fred() { fnPointer = bla; }

    > };
    >
    > Good luck...
    >
    > - Jay
     
    Jay Nabonne, Jul 28, 2005
    #12
  13. Ian wrote:
    > Victor Bazarov wrote:
    >> Ian wrote:
    >>
    >>> In an ideal world, I wanted something like:
    >>>
    >>> extern "C" {
    >>> template <typename T> int bla() { return T().bla(); }
    >>> }
    >>>
    >>> so I could set up the C struct thus:
    >>>
    >>> template <typename T>
    >>> struct Fred : FredFromC
    >>> {
    >>> Fred() { fnPointer = bla<T>; }
    >>> };
    >>>
    >>> Where fnPointer is a member of FredFromC.

    >>
    >>
    >> And how is it going to be used?
    >>

    > By the operating system as a callback into the driver. FredFromC is a
    > structure defined by the OS to be populated with callbacks for various
    > driver functions.


    Sorry, that basically means nothing here. You should consider posting
    the C code that calls whatever callbacks you are trying to define.

    V
     
    Victor Bazarov, Jul 28, 2005
    #13
  14. Ian

    Ian Guest

    Victor Bazarov wrote:
    > Ian wrote:
    >
    >>Victor Bazarov wrote:
    >>
    >>>Ian wrote:
    >>>
    >>>
    >>>>In an ideal world, I wanted something like:
    >>>>
    >>>>extern "C" {
    >>>> template <typename T> int bla() { return T().bla(); }
    >>>>}
    >>>>
    >>>>so I could set up the C struct thus:
    >>>>
    >>>>template <typename T>
    >>>>struct Fred : FredFromC
    >>>>{
    >>>> Fred() { fnPointer = bla<T>; }
    >>>>};
    >>>>
    >>>>Where fnPointer is a member of FredFromC.
    >>>
    >>>
    >>>And how is it going to be used?
    >>>

    >>
    >>By the operating system as a callback into the driver. FredFromC is a
    >>structure defined by the OS to be populated with callbacks for various
    >>driver functions.

    >
    >
    > Sorry, that basically means nothing here. You should consider posting
    > the C code that calls whatever callbacks you are trying to define.
    >

    It's part of an operating system and I don't have it.

    The calling code is irrelevant to the original question. I'm still none
    the wiser as to why template functions can't be given extern "C" linkage.

    Apart form the mangled name, a template function is (well OK, can be) no
    different than any other with the same signature:

    #include <iostream>

    template <typename T> void tem( int n ) { std::cout << n << std::endl; }
    void normal( int n ) { std::cout << n*2 << std::endl; }

    typedef void (*Fn)( int );

    int
    main()
    {
    Fn fn1 = &tem<int>;
    Fn fn2 = &normal;

    fn1( 2 );
    fn2( 2 );
    }

    but we can't do

    extern "C"{
    template <typename T> void tem( int n ) {}
    void normal( int n ) {}

    typedef void (*Fn)( int );
    }

    Ian
     
    Ian, Jul 28, 2005
    #14
  15. Ian wrote:
    > [..]
    > The calling code is irrelevant to the original question. I'm still
    > none the wiser as to why template functions can't be given extern "C"
    > linkage.


    (a) It doesn't make sense since there is no way to use templates
    from C -- it just doesn't have that mechanism. To learn more on
    "why" certain things the way they are, post to comp.std.c++, that
    is the "why" newsgroup. We here talk mostly "how".

    > Apart form the mangled name, a template function is (well OK, can be)
    > no different than any other with the same signature:


    (b) I think you're a bit confused. There are no "template functions".
    There are only "function templates". What you have here is
    a template, not a function.

    (c) Templates can have linkage, but they cannot have "C" linkage because
    the Standard prohibits it in 14/4.

    > #include <iostream>
    >
    > template <typename T> void tem( int n ) { std::cout << n <<
    > std::endl; } void normal( int n ) { std::cout << n*2 << std::endl; }
    >
    > typedef void (*Fn)( int );
    >
    > int
    > main()
    > {
    > Fn fn1 = &tem<int>;
    > Fn fn2 = &normal;


    There is no need for '&' here, BTW

    >
    > fn1( 2 );
    > fn2( 2 );
    > }
    >
    > but we can't do
    >
    > extern "C"{
    > template <typename T> void tem( int n ) {}
    > void normal( int n ) {}
    >
    > typedef void (*Fn)( int );
    > }


    Correct, we can't.

    V
     
    Victor Bazarov, Jul 28, 2005
    #15
  16. Ian

    Ian Guest

    Victor Bazarov wrote:
    > Ian wrote:
    >
    >>[..]
    >>The calling code is irrelevant to the original question. I'm still
    >>none the wiser as to why template functions can't be given extern "C"
    >>linkage.

    >
    >
    > (a) It doesn't make sense since there is no way to use templates
    > from C -- it just doesn't have that mechanism. To learn more on
    > "why" certain things the way they are, post to comp.std.c++, that
    > is the "why" newsgroup. We here talk mostly "how".
    >

    A function template could be called indirectly through a function pointer.
    >
    >>Apart form the mangled name, a template function is (well OK, can be)
    >>no different than any other with the same signature:

    >
    >
    > (b) I think you're a bit confused. There are no "template functions".
    > There are only "function templates". What you have here is
    > a template, not a function.
    >

    OK, I got the name the wrong way round, but I'm not confused.

    > (c) Templates can have linkage, but they cannot have "C" linkage because
    > the Standard prohibits it in 14/4.
    >

    True, but it doesn't appear to say why.

    Ian
     
    Ian, Jul 28, 2005
    #16
  17. Ian wrote:
    > Victor Bazarov wrote:
    >> Ian wrote:
    >>
    >>> [..]
    >>> The calling code is irrelevant to the original question. I'm still
    >>> none the wiser as to why template functions can't be given extern
    >>> "C" linkage.

    >>
    >>
    >> (a) It doesn't make sense since there is no way to use templates
    >> from C -- it just doesn't have that mechanism. To learn more on
    >> "why" certain things the way they are, post to comp.std.c++, that
    >> is the "why" newsgroup. We here talk mostly "how".
    >>

    > A function template could be called indirectly through a function
    > pointer.


    No, it cannot. Only an instantiation of it or a specialisation of it
    can.

    >>> Apart form the mangled name, a template function is (well OK, can
    >>> be) no different than any other with the same signature:

    >>
    >>
    >> (b) I think you're a bit confused. There are no "template
    >> functions". There are only "function templates". What you have
    >> here is a template, not a function.
    >>

    > OK, I got the name the wrong way round, but I'm not confused.


    You hope...

    >
    >> (c) Templates can have linkage, but they cannot have "C" linkage
    >> because the Standard prohibits it in 14/4.
    >>

    > True, but it doesn't appear to say why.


    Nor is it supposed to. That's what 'comp.std.c++' is for.

    V
     
    Victor Bazarov, Jul 28, 2005
    #17
  18. * Ian:
    > Victor Bazarov wrote:
    > > Ian wrote:
    > >
    > >>[..]
    > >>The calling code is irrelevant to the original question. I'm still
    > >>none the wiser as to why template functions can't be given extern "C"
    > >>linkage.

    > >
    > >
    > > (a) It doesn't make sense since there is no way to use templates
    > > from C -- it just doesn't have that mechanism. To learn more on
    > > "why" certain things the way they are, post to comp.std.c++, that
    > > is the "why" newsgroup. We here talk mostly "how".
    > >

    > A function template could be called indirectly through a function pointer.


    You don't need 'extern "C"' to do that.


    > >>Apart form the mangled name, a template function is (well OK, can be)
    > >>no different than any other with the same signature:

    > >
    > >
    > > (b) I think you're a bit confused. There are no "template functions".
    > > There are only "function templates". What you have here is
    > > a template, not a function.
    > >

    > OK, I got the name the wrong way round, but I'm not confused.


    I agree with Victor, you're a little bit confused here, probably because of
    lack of knowledge of the practical stuff not mentioned in the standard.


    > > (c) Templates can have linkage, but they cannot have "C" linkage because
    > > the Standard prohibits it in 14/4.
    > >

    > True, but it doesn't appear to say why.


    Because "C" linkage is meant to be compatible with C (the same vendor's C
    compiler), where _in practice_ function names have very simple ornamentation
    in the object code -- the names that the linker sees. For example, 'foo'
    in the source code will, with C linkage, typically end up as '_foo' in the
    object code. There is nothing there to distinguish this foo from other
    instantiations or other foo functions with different arguments. In short, C
    does not support function name overloading. And a function template can be
    regarded as an extreme case of overloading, a kind of ininite overloading.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 28, 2005
    #18
  19. Ian

    Ian Guest

    Alf P. Steinbach wrote:
    > * Ian:
    >
    >>Victor Bazarov wrote:
    >>
    >>>Ian wrote:
    >>>
    >>>
    >>>>[..]
    >>>>The calling code is irrelevant to the original question. I'm still
    >>>>none the wiser as to why template functions can't be given extern "C"
    >>>>linkage.
    >>>
    >>>
    >>>(a) It doesn't make sense since there is no way to use templates
    >>> from C -- it just doesn't have that mechanism. To learn more on
    >>> "why" certain things the way they are, post to comp.std.c++, that
    >>> is the "why" newsgroup. We here talk mostly "how".
    >>>

    >>
    >>A function template could be called indirectly through a function pointer.

    >
    >
    > You don't need 'extern "C"' to do that.
    >

    We're going round in circles here, you do to assign an instantiation of
    a function template to a extern "C' function pointer.
    >
    > I agree with Victor, you're a little bit confused here, probably because of
    > lack of knowledge of the practical stuff not mentioned in the standard.
    >

    I've been doing the practical stuff since the early days of cfront
    compilers, so I know quite a lot about what goes on under the hood.
    >
    > Because "C" linkage is meant to be compatible with C (the same vendor's C
    > compiler), where _in practice_ function names have very simple ornamentation
    > in the object code -- the names that the linker sees. For example, 'foo'
    > in the source code will, with C linkage, typically end up as '_foo' in the
    > object code. There is nothing there to distinguish this foo from other
    > instantiations or other foo functions with different arguments. In short, C
    > does not support function name overloading. And a function template can be
    > regarded as an extreme case of overloading, a kind of ininite overloading.
    >

    That's why C++ uses name mangling. Which is probably why the standard
    forbids function templates from having extern "C" linkage, as there is
    no way for C to call a mangled function directly.

    But it would still be nice to be able to assign an instantiation of a
    function template to a extern "C' function pointer.

    Ian
     
    Ian, Jul 28, 2005
    #19
  20. * Ian:
    > * Alf P. Steinbach:
    > > * Ian:
    > > > * Victor Bazarov:
    > > > > * Ian:
    > > > > > [..]
    > > > > > The calling code is irrelevant to the original question. I'm still
    > > > > > none the wiser as to why template functions can't be given extern "C"
    > > > > > linkage.
    > > > >
    > > > > (a) It doesn't make sense since there is no way to use templates
    > > > > from C -- it just doesn't have that mechanism. To learn more on
    > > > > "why" certain things the way they are, post to comp.std.c++, that
    > > > > is the "why" newsgroup. We here talk mostly "how".
    > > >
    > > > A function template could be called indirectly through a function pointer.

    > >
    > >
    > > You don't need 'extern "C"' to do that.
    > >

    > We're going round in circles here, you do to assign an instantiation of
    > a function template to a extern "C' function pointer.


    Oh, sorry for jumping into the middle of a thread; I missed that bit of
    context, if it was ever there.

    Yes, it seems that's so.

    But consider: to interface to C code everything about the function signature
    is fixed, so all you have to do is to introduce an in-between 'extern "C"'
    function calling your template code.


    > > I agree with Victor, you're a little bit confused here, probably because of
    > > lack of knowledge of the practical stuff not mentioned in the standard.
    > >

    > I've been doing the practical stuff since the early days of cfront
    > compilers, so I know quite a lot about what goes on under the hood.
    > >
    > > Because "C" linkage is meant to be compatible with C (the same vendor's C
    > > compiler), where _in practice_ function names have very simple ornamentation
    > > in the object code -- the names that the linker sees. For example, 'foo'
    > > in the source code will, with C linkage, typically end up as '_foo' in the
    > > object code. There is nothing there to distinguish this foo from other
    > > instantiations or other foo functions with different arguments. In short, C
    > > does not support function name overloading. And a function template can be
    > > regarded as an extreme case of overloading, a kind of ininite overloading.
    > >

    > That's why C++ uses name mangling. Which is probably why the standard
    > forbids function templates from having extern "C" linkage, as there is
    > no way for C to call a mangled function directly.


    Right, you got it.


    > But it would still be nice to be able to assign an instantiation of a
    > function template to a extern "C' function pointer.


    See above, although many compilers such as MSVC already allow this, as an
    extension, and although I agree that it would be nice and not only for
    template functions, but also for static member functions. The problem here
    is that C linkage seems to have been intended to address two different
    practical aspects of linkage: name mangling, and machine code level calling
    convention. For pointers the former is irrelevant, but the latter is still
    relevant. In MSVC the calling convention is specified via a language
    extension, not via the C/C++ linkage. And so MSVC can allow such pointers.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jul 28, 2005
    #20
    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:
    627
    usr2003
    Sep 19, 2003
  2. Steve Kobes

    extern and linkage

    Steve Kobes, Jun 9, 2004, in forum: C Programming
    Replies:
    1
    Views:
    303
    Chris Torek
    Jun 9, 2004
  3. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,137
    Smokey Grindel
    Dec 2, 2006
  4. Replies:
    1
    Views:
    606
    Michael DOUBEZ
    Sep 12, 2008
  5. Stanisław Findeisen

    extern "C" friend function without external linkage

    Stanisław Findeisen, Aug 25, 2010, in forum: C++
    Replies:
    2
    Views:
    2,198
    Goran Pusic
    Aug 26, 2010
Loading...

Share This Page