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.


Reply via email to