By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,812 Members | 1,324 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,812 IT Pros & Developers. It's quick & easy.

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

P: n/a
Ian
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
Jul 27 '05 #1
Share this Question
Share on Google+
22 Replies


P: n/a
Ian <no***@nowhere.com> 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....)
Jul 27 '05 #2

P: n/a
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
Jul 27 '05 #3

P: n/a
Ian
Andre Kostur wrote:
Ian <no***@nowhere.com> 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
Jul 27 '05 #4

P: n/a
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

Jul 27 '05 #5

P: n/a
Ian
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
Jul 27 '05 #6

P: n/a
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

Jul 28 '05 #7

P: n/a
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
Jul 28 '05 #8

P: n/a
Ian
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
Jul 28 '05 #9

P: n/a
Ian
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
Jul 28 '05 #10

P: n/a
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

Jul 28 '05 #11

P: n/a
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


Jul 28 '05 #12

P: n/a
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
Jul 28 '05 #13

P: n/a
Ian
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
Jul 28 '05 #14

P: n/a
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
Jul 28 '05 #15

P: n/a
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.
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
Jul 28 '05 #16

P: n/a
* 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?
Jul 28 '05 #17

P: n/a
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
Jul 28 '05 #18

P: n/a
Ian
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
Jul 28 '05 #19

P: n/a
* 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?
Jul 28 '05 #20

P: n/a
Ian
Alf P. Steinbach wrote:
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.


This looks to be a good idea, unfortunately Sun's compiler is rather
pedantic in this area (maybe something to do the the author being the
C++ standard committee chairman!). I suppose I could disable the
warning and get on with life.

Cheers,

Ian
Jul 28 '05 #21

P: n/a
Ian wrote:
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

C has no concept of multiple objects with the same name. It can't
even deal with simple function overloads, let alone templates.
Jul 28 '05 #22

P: n/a
Me
Ian wrote:
The title says it all.
I can't really tell from reading the rest of this thread what problem
you're trying to solve, but I'm assuming you have an pointer to an
extern "C" function and you want to assign a template function to it.
The portable way to do this is create an extern "C" wrapper function
around an instance of the template and take the address of it, but a
solution that works in practice is to just reinterpret_cast it to the
extern "C"'d type. I'd probably go with the wrapper function way though
since I don't like reinterpret_casts in my code.
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.


7.5/6 "At most one function with a particular name can have C language
linkage. Two declarations for a function with C language linkage with
the same function name (ignoring the namespace names that qualify it)
that appear in different namespace scopes refer to the same function."

Since a template function has one name but can be parameterized to
refer to different functions, this obviously can't work. It looks like
this shouldn't be a problem for template functions with internal
linkage but the standard doesn't make a special case to allow for that.
comp.std.c++ is a better place to discuss that though.

Jul 29 '05 #23

This discussion thread is closed

Replies have been disabled for this discussion.