extern(C++, ns)

Walter Bright via Digitalmars-d digitalmars-d at puremagic.com
Sun Jan 3 00:03:54 PST 2016


On 1/2/2016 10:39 PM, Manu via Digitalmars-d wrote:
> On 3 January 2016 at 15:40, Walter Bright via Digitalmars-d
> <digitalmars-d at puremagic.com <mailto:digitalmars-d at puremagic.com>> wrote:
>
>     On 1/2/2016 8:54 PM, Manu via Digitalmars-d wrote:
>
>         C++ namespacing is causing me endless, and I mean *endless* trouble.
>         This idea that we express the C++ namespace hierarchy in D is the main
>         problem.
>         I don't think C++ namespaces should interfere with D scoping rules, they
>         should
>         be purely for mangling.
>         It creates a whole bundle of edge cases which either don't have work
>         arounds, or
>         REALLY awkward workarounds which typically have a heavy impact on all the
>         regular D code that the C++ code interacts with.
>
>         Not least of which is that C++ namespaces usually span the entire
>         project, and
>         in D a C++ namespace can only appear in one module ever.
>         Declaring symbols with the same C++ namespace in different modules leads to
>         multiple definition errors, and if you are super-careful to avoid those, you
>         gain name resolution issues in it's place.
>
>
>     That works the same as in C++. Don't define the same symbol in the same C++
>     namespace in multiple modules. It doesn't work in C++, and doesn't work in D
>     for exactly the same reason.
>
> I'm not defining the same symbols, I'm defining different symbols, just inside
> the same namespace.

Then how do they wind up with the same mangled name? Please give an example.


>         The main problem extends from this situation:
>
>         module x.y;
>
>         extern(C++, ns) struct Y {}
>
>
>         module ns.m;
>
>         import x.y; // fail, the c++ namespace is already present (top level module)
>
>     Doesn't fail when I try it.
>
> Import another module with the same namespace, have the objects within each
> instance of the namespace refer to eachother.

You'll have to post an example.

>         static import x.y;
>         alias Y = x.y.Y;
>      Nothing wrong with that.
> Except that it doesn't always work.

I can't help with statements like "not always", "seems to", "sometimes", etc.

> It also implies that I must double the number of modules I have, so that I can
> wrap every module with a C++ namespace in an outer one without it.

I have no idea why you must do that.

>     You can do that in D as well, as long as you follow the One Definition Rule,
>     which you have to with C++ code anyway.
>
>
> It doesn't scale though.
>
> module x.x;
> import x.y;
>
> extern(C++, ns)
> {
>    class X { Y y; }
> }
>
>
> module x.y;
> import x.x;
> extern(C++, ns)
> {
>    class Y { X x; }
> }
>
>
> Error: undefined identifier 'Y'

First off, please do not write code like that. If you find yourself doing such 
routinely, AAAAIIIIEEEEEE !!!! :-) I understand that people can and will write 
code like that, and I will try and help you get it to work anyway.

Secondly, it points out a misunderstanding of how namespace lookup works in D. 
Namespaces in D:

1. follow D lookup rules
2. follow C++ mangling rules

The example of:
     Y y;
is clearly assuming that C++ namespace lookup rules are being followed. They are 
not, D lookup rules are. Y is declared in x.y.ns, not x.x.ns. As far as the 
compiler is concerned, x.y.ns and x.x.ns are different namespaces (although they 
will mangle the same). Thus, "Y" should be "x.y.ns.Y".

You can see this if you replace "extern(C++, ns)" with "struct ns". You'll get 
the SAME error message!

The following should work, according to the scoping rules:

-----------x.d------------
import y;

//struct ns
extern (C++, ns)
{
     class X { y.ns.Y a; }
}

----------y.d------------
import x;

//struct ns
extern (C++, ns)
{
     class Y { x.ns.X b; }
}

It does work if the struct is used. This illustrates how symbol lookup works. I 
don't know why that example doesn't work, but have filed:

   https://issues.dlang.org/show_bug.cgi?id=15503

because it should work (it works when 'struct' is used, and the name lookup 
should be the same).

> You would put it in its own module like normal D code, and let normal D symbol
> resolution take care of it.
> That's surely the preferred approach anyway? Chances are, your D module
> structure will match the C++ module structure verbatim anyway, which will have
> already been structured that way.

C++ doesn't have a module structure, and the way you propose cannot work in D, 
since D does not have a global scope. If I implemented your method, the first 
bug report from you will be:

     ---
     int x;
     extern (C++, ns) { char x; }
     ---
     error: multiple definition of x

You'll say "but it is in a different namespace, so I should be able to declare 
another x!" and you would be right. It will also be impossible to connect to C++ 
code that defines the same identifier in different namespaces.


> It's endlessly difficult, and it's really hard to summarise.

I don't need a summary, I need specific cases.


> There was a binary decision made; as far as I know, the decision was made on a
> whim, there was no design committee, a decision was simply chosen.
> I know of no argument that demonstrates that the current state is correct, but I
> have months of wasted time and energy that prove that it's wrong. Why do I need
> to now take even more time to construct an elaborate suite of examples to
> demonstrate my argument?

Producing cases that fail should have been a byproduct of the production of code 
that failed. In any case, without examples that illustrate the problem(s) you're 
having, I cannot help.


> I can't get work done. I've spent all the free time I have trying, and I'd
> rather write code than spend my time reducing test cases.
> Try and bind to a reasonably complex C++ project and you will discover the same
> thing... or don't, I've honestly already done that work for you!

I appreciate that you've done the work for me, but I'd have to start over from 
scratch because you don't provide examples that don't work, and I'd have to 
guess what you were trying to do, which never works out very well.


> Please don't make me waste endlessly more of my time, I don't have energy left
> to spare. This is precisely what's driving me away from D. I can't take it
> anymore, everything hits brick walls, I am so frustrated, I just want to have a
> **SINGLE** win, where I can complete a single real-world project and say I have
> written something that works!

I hope that you'll come here and ask for help before you've expended endless 
hours beating your head :-(


> If you're not convinced, then start by fixing the forward referencing issues.

I don't know of any bugzilla issues with that.



More information about the Digitalmars-d mailing list