extern(C) and mangling type names

Mike Parker via Digitalmars-d digitalmars-d at puremagic.com
Tue Feb 14 22:20:23 PST 2017


On Wednesday, 15 February 2017 at 04:49:07 UTC, Walter Bright 
wrote:
> On 2/14/2017 7:40 PM, Mike Parker wrote:
>> So, should extern(C) turn off mangling for types?
>
> In C, it is common to have opaque types like `struct Foo;` all 
> over the place, and maybe `struct Foo { ... };` appear in 
> multiple times. This works in C.
>
> It doesn't work in D, even if the name is set as `extern (C)`. 
> That's because there is no C symbol table in the compiler, it's 
> still a D symbol and follows D lookup rules. Thus, repeatedly 
> declaring `struct Foo` will result in collisions.

OK, the 'C symbol table' vs. 'D symbol table' bit clarifies it 
for me. I had a misunderstanding about extern(C)'s application.

So with this, my understanding now is that extern(C) only comes 
into play when the mangled name is generated for the object file. 
Until that time, the compiler only sees the fully-qualified name. 
Since types don't go to the object file, there's no effect. I was 
under the mistaken impression that this behaved as I wanted the 
types to:

module ec1;
extern(C) void bar();
pragma(msg, bar.mangleof);

module ec2;
extern(C) void bar() { import std.stdio; writeln("bar"); }
pragma(msg, bar.mangleof);

module ec3;
void main() {
     import ec1, ec2;
     bar();
}

But that is obviously not the case (as I would have discovered 
had I tried it out):

ec3.d(4): Error: ec2.bar at ec2.d(2) conflicts with ec1.bar at 
ec1.d(2)

>
> The solution is to declare `struct Foo` in one file, and have 
> the others import that file.

Yes, as I've long been doing with some of the bindings in 
Derelict. Unfortunately, that's not a solution for the specific 
use case that prompted this post. I'll either have to resort to 
using aliases to void* or template mixins.




More information about the Digitalmars-d mailing list