www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Why extern variables and functions within template/struct/class have a

reply "Igor Stepanov" <wazar.leollone yahoo.com> writes:
Is it correct?
When I wrote next code:
template Extern(string s)
{
     mixin("static extern(C) extern int "~s~";"~
     "alias Extern = "~s~";");
}
void main()
{
     writeln(&Extern!("xxx"));
}
I get error message "undefined reference to 
`_D1a24__T6ExternVAyaa3_787878Z3xxxi'", when I expect to get 
"undefined reference to `xxx'"?
Is it error?
May 07 2013
next sibling parent "Igor Stepanov" <wazar.leollone yahoo.com> writes:
May be I need to fix that issue? What about functions?

struct Foo
{
   extern(C) void bar()
   {

   }
}

Is it good to set bar mangling to "bar"?
May 07 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/7/13, Igor Stepanov <wazar.leollone yahoo.com> wrote:
 struct Foo
 {
    extern(C) void bar()
    {

    }
 }

 Is it good to set bar mangling to "bar"?

No. For one example, internal extern(C) functions can be used for callbacks. You wouldn't want linking to fail if you have this code: struct A { extern(C) void callback() { } } struct B { extern(C) void callback() { } }
May 08 2013
prev sibling next sibling parent "Dicebot" <m.strashun gmail.com> writes:
On Wednesday, 8 May 2013 at 09:09:34 UTC, Andrej Mitrovic wrote:
 ...

Suck code is invalid in C++ and for a good reason. I'd really expect D to refuse to compile extern(C) functions it can't possibly mangle correctly.
May 08 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/8/13, Dicebot <m.strashun gmail.com> wrote:
 On Wednesday, 8 May 2013 at 09:09:34 UTC, Andrej Mitrovic wrote:
 ...

Suck code is invalid in C++ and for a good reason. I'd really expect D to refuse to compile extern(C) functions it can't possibly mangle correctly.

Sorry, I forgot I was actually thinking about *static* extern(C) functions. I'm not sure about methods.
May 08 2013
prev sibling next sibling parent "Dicebot" <m.strashun gmail.com> writes:
On Wednesday, 8 May 2013 at 09:22:52 UTC, Andrej Mitrovic wrote:
 On 5/8/13, Dicebot <m.strashun gmail.com> wrote:
 On Wednesday, 8 May 2013 at 09:09:34 UTC, Andrej Mitrovic 
 wrote:
 ...

Suck code is invalid in C++ and for a good reason. I'd really expect D to refuse to compile extern(C) functions it can't possibly mangle correctly.

Sorry, I forgot I was actually thinking about *static* extern(C) functions. I'm not sure about methods.

static methods are illegal in C++ with extern(C) too. As well as any namespaced function. Or any function that has overloads.
May 08 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/8/13, Dicebot <m.strashun gmail.com> wrote:
 static methods are illegal in C++ with extern(C) too.

I don't see why. They're useful in D anyway.
May 08 2013
prev sibling next sibling parent "Dicebot" <m.strashun gmail.com> writes:
On Wednesday, 8 May 2013 at 09:46:00 UTC, Andrej Mitrovic wrote:
 On 5/8/13, Dicebot <m.strashun gmail.com> wrote:
 static methods are illegal in C++ with extern(C) too.

I don't see why. They're useful in D anyway.

Because they have namespace (class namespace) and can't be mangled according to C rules. Exactly your example. You can't have two "foo"'s there but any other naming scheme IS NOT C mangling but some weird abomination that pretends to be it. Thus it is a compile-time error.
May 08 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/8/13, Dicebot <m.strashun gmail.com> wrote:
 Because they have namespace (class namespace) and can't be
 mangled according to C rules. Exactly your example. You can't
 have two "foo"'s there but any other naming scheme IS NOT C
 mangling but some weird abomination that pretends to be it. Thus
 it is a compile-time error.

Right, you may not be able to statically link with it but it's still a calling convention, so it's useful (for callbacks).
May 08 2013
prev sibling next sibling parent "Dicebot" <m.strashun gmail.com> writes:
On Wednesday, 8 May 2013 at 09:56:14 UTC, Andrej Mitrovic wrote:
 On 5/8/13, Dicebot <m.strashun gmail.com> wrote:
 Because they have namespace (class namespace) and can't be
 mangled according to C rules. Exactly your example. You can't
 have two "foo"'s there but any other naming scheme IS NOT C
 mangling but some weird abomination that pretends to be it. 
 Thus
 it is a compile-time error.

Right, you may not be able to statically link with it but it's still a calling convention, so it's useful (for callbacks).

Well, that is one of rather inconvenient issues with D handling of emitting symbols (this one kind of inherited from C++). extern(X) defines both mangling and calling convention. You can't have those separately now. Saying in one case it is both mangling and ABI and in other one it is only ABY smells like broken specification/implementation. Actually I remember discussing this with Volt language team recently. Currently relation between D type system and emitted symbols is not that well-defined in spec and this is one of many cases where it causes problems. I don't think it can be fixed without some sort of overhaul.
May 08 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/8/13, Dicebot <m.strashun gmail.com> wrote:
 Well, that is one of rather inconvenient issues with D handling
 of emitting symbols (this one kind of inherited from C++).
 extern(X) defines both mangling and calling convention. You can't
 have those separately now.

Yeah. I suppose the ideal situation would be to have extern(C) follow strict C mangling and calling convention (meaning no mangling for nested extern(C) symbols), and have a separate linkage(C) feature to be used when we want to set the linkage of a symbol (well, it's probably only useful for functions) but let the compiler mangle it any way it wants to (to avoid any symbol clashes). There's a pull request somewhere which enables setting custom mangle names for symbols, so we'll at least have the flexibility in picking symbol names that we need.
May 08 2013
prev sibling next sibling parent "Dicebot" <m.strashun gmail.com> writes:
On Wednesday, 8 May 2013 at 10:28:40 UTC, Andrej Mitrovic wrote:
 I suppose the ideal situation would be to have extern(C) follow 
 strict
 C mangling and calling convention (meaning no mangling for 
 nested
 extern(C) symbols), and have a separate linkage(C) feature to 
 be used
 when we want to set the linkage of a symbol (well, it's 
 probably only
 useful for functions) but let the compiler mangle it any way it 
 wants
 to (to avoid any symbol clashes).

 There's a pull request somewhere which enables setting custom 
 mangle
 names for symbols, so we'll at least have the flexibility in 
 picking
 symbol names that we need.

That may work as temporarily solution but I really think it is just hiding forest behind the trees. That part of language needs some serious attention at one point, not just few pull requests. To define all possible linkage modifiers. To define possible mangling modifiers. To define symbol visibility. For example, do you remember discussion about classes and provable method (non-)virtuality? Which ended at a conclusion that it can't work because class can be inherited from anywhere, for example from called dll. Funny thing we have an "export" as a protection attribute: "Export means that any code outside the executable can access the member. Export is analogous to exporting definitions from a DLL." Cool. Problem is access/visibility rules for symbols that are _not_ marked with "export" is not defined and looking and generated binaries is not enforced in any way by dmd at least. Which makes export kind of joke. Well, pardon me, I probably have exceeded my allowed daily rant limit :)
May 08 2013
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/8/13, Dicebot <m.strashun gmail.com> wrote:
 Well, pardon me, I probably have exceeded my allowed daily rant
 limit :)

Don't worry, and I agree with you. But I think it's probably too late to actually change what a linkage specifier does for nested symbols. We might end up getting duplicate symbol definition errors (hello Optlink..) in completely unrelated libraries if mangling changes for these symbols.
May 08 2013
prev sibling parent "Igor Stepanov" <wazar.leollone yahoo.com> writes:
On Wednesday, 8 May 2013 at 19:14:14 UTC, Andrej Mitrovic wrote:
 On 5/8/13, Dicebot <m.strashun gmail.com> wrote:
 Well, pardon me, I probably have exceeded my allowed daily rant
 limit :)

Don't worry, and I agree with you. But I think it's probably too late to actually change what a linkage specifier does for nested symbols. We might end up getting duplicate symbol definition errors (hello Optlink..) in completely unrelated libraries if mangling changes for these symbols.

I've undestood, that function mangling is a difficult issue. But what about extern variables? Obviously, when user write ("extern(C) extern int var;"), he want to get extern variable with C mangling. Another way: get second parameter (symbol name) to extern attribute. E.g. extern(C, " FOO ")void FOO(int); //have C linkage and FOO mangling extern(C)void FOO2(int); //have C linkage and C (or D, if FOO2 is local symbol) mangling extern("__FOO__") void FOO(int); //have D or System linkage and "__FOO__" mangling However, I would like to mangling argument of extern attribute will be evaluatable form any string expression. enum MANGLING = " M "; extern(D, MANGLING) int boo();
May 09 2013