Trouble understanding crash when class is returned by value from C++

Andrej Mitrovic andrej.mitrovich at gmail.com
Mon Sep 3 10:15:54 PDT 2012


On 9/3/12, Iain Buclaw <ibuclaw at ubuntu.com> wrote:
> Indeed,  C++ classes are always passed in memory by design.  Whereas
pointers could be passed in registers.

That's cool. I learn something new every day. :)

> And this is one
> reason why you need to ensure that function signatures match in both D
> and C/C++ code.

Yeah that's doable when the type is a POD but when it's a class
returned by value there is no equivalent in D since D classes are
always references, so I can't match the D function signature to the C
one.

> extern "C"
> FileName value_FileName(void* refVal)
> {
>     return *(FileName*)refVal;
> }

That won't work either since FileName is still in the return type and
I can't match the function signature on the D side (it still crashes).
The only thing I can think of is to match the C++ function signature
to the D side via something like:

C++:
class FileName { ... } // same as before

struct Fake
{
    char __thunk[4];
};

Fake value_FileName(void* refVal)
{
    return *(Fake*)(&(*(FileName*)refVal));
}

It's ugly but it does seem to work and matches the D function
signature. It would be a lot simpler if the return type was castable
to (char[4]), but C/++ doesn't support returning arrays by value. :)

> By the way, why extern "C" when extern (C++) works just fine? :-)

I'm working on a codegenerator which uses C as the glue language,
similar to SWIG. But the plan is to support more features than SWIG
and have a faster and less memory-intensive cross-language virtual
method invocation mechanism. Unlike SWIG I support passing PODs by
value, but passing non-POD classes by value was problematic and I can
see now why.

Thanks for your help guys!


More information about the D.gnu mailing list