extern(C++, ns)

Manu via Digitalmars-d digitalmars-d at puremagic.com
Sat Jan 2 22:39:11 PST 2016


On 3 January 2016 at 15:40, Walter Bright via Digitalmars-d <
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.


It is also very awkward that a C++ namespace can't be the same as a top
>> level
>> package name. My top level package is named the same as one of my C++
>> namespaces... what do I do? It gets ugly real fast.
>>
>> 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.


import x.y : Y; // fail, not found
>>
>
> Again, Y is not module scope.
>
> // This **sometimes** works,
>>
>
> sometimes?


Yes, it works sometimes.


and it's very brittle
>>
>
> ??


It only 'sometimes' works. Reasons are not clear.


static import x.y;
>> alias Y = x.y.Y;
>>
>
> Nothing wrong with that.


Except that it doesn't always work.
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.


Thing is, I'm not declaring a C++ object, I'm declaring a D object,  the
>> only
>> thing being that struct's take care to maintain common binary layout, and
>> functions just mangle like C++ so that my code links. I'm in D, I'm
>> declaring my
>> stuff in the D module where it should be scoped, and where other D code
>> should
>> expect to find it. I don't see any point in building the C++ hierarchy in
>> this
>> space. C++ namespace rules are incompatible with D; you can litter them
>> through
>> C++ code, and add new symbols to C++ namespaces from anywhere...
>>
>
> 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'


this is
>> fundamentally incompatible with D, and no further reasoning should be
>> required
>> to conclude that it can't be reproduced, so it should be for mangling
>> purposes only.
>>
>
> I guarantee you that if we'd implemented it that way, you'd have a long
> litany of complaints about that, because the compiler could not distinguish
> Y from ns.Y.


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.

I have spent **days**, actually, weeks of my free time trying to make my
>> tiny
>> bit of code build, and it's just nothing but trouble after trouble. I have
>> completely restructured my code at least 3 times to try and find a way to
>> make
>> it fit together in a way that's both practical and works, but I just
>> can't. It
>> always hits some brick wall somewhere.
>>
>> extern(C++, NS) looks okay in isolated tests/experiments, but try and
>> actually
>> use it, and you will become very frustrated.
>>
>> Please, fix this. I'm almost done. I'm really struggling to keep this
>> dream alive.
>>
>
> I do not understand what difficulty you are having with this.
>

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

I'm telling you this; as someone who's endlessly fought with this in
practical real-world applications, the design is wrong.
D has module scoping, it works, let D's scoping do it's job. This design
can lead to nothing but edge cases. We have plenty of edges already.

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?

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!
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!

If you're not convinced, then start by fixing the forward referencing
issues. They are just bugs, and I highly suspect that many of my tests and
experiments have been hindered by the fact that there are actually 2-3
issues working here in tandem. The error messages all look basically the
same and offer no help. Forward referencing issue == "undefined
identifier", namespace conflict == "undefined identifier". I suspect that
cases exist where I was testing one thing, and the other thing jumped in
and caused a mis-diagnosis.

That doesn't mean it's not wrong though... let the D module system do what
it's designed to do. The point of extern(C++) is to present a C++ API to a
D user, so it needs to be arranged in D's terms or the user will feel very
uncomfortable, and the author will have to jump through more hoops than if
they just stuck with C++.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20160103/5e25b9cc/attachment.html>


More information about the Digitalmars-d mailing list