Returning structs from COM

kinke via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Dec 19 01:49:13 PST 2016


On Saturday, 3 December 2016 at 09:51:00 UTC, John C wrote:
> Some DirectX methods return structs by value, but when I try 
> calling them I either get garbage or an access violation.
>
> Usually COM methods return structs by pointer as a parameter, 
> but these are returning the struct as the actual return value, 
> as in this definition:
>
>   extern(Windows):
>   struct D2D1_SIZE_F { float width, height; }
>
>   interface ID2D1Bitmap : ID2D1Image {
>     D2D1_SIZE_F GetSize();
>   }
>
> If I rewrite GetSize to return by pointer as a parameter, it 
> appears to work and I get the correct width and height without 
> an AV being thrown. And I can add a helper method that returns 
> by value:
>
>   interface ID2D1Bitmap : ID2D1Image {
>     void GetSize(D2D1_SIZE_F* size);
>
>     final D2D1_SIZE_F GetSize() {
>       D2D1_SIZE_F size;
>       GetSize(&size);
>       return size;
>     }
>   }
>
> But does anyone know why the original definition works in C++ 
> but not D? Is it a bug? (I'm compiling with -m64.)

That's rather interesting. The COM function really seems to 
return the struct directly, not returning an HRESULT and setting 
some output pointee as most COM functions I've seen so far. 
According to the Win64 ABI, the returned D2D1_SIZE_F struct 
should be returned in RAX, as the 2 floats are <= 64 bit. But 
your workaround seems to suggest it's using sret (struct-return 
via hidden pointer). To make sure this is the case, I'd suggest 
inspecting the C++ assembly for a trivial function. If so, we'll 
need to find out why the Win64 ABI isn't followed and whether COM 
has its own ABI.

> I know for ldc that function that return struct by value 
> actually return by a hidden return parameter pointer.

Not always. In fact, it highly depends on the target ABI which 
structs are returned in registers and which ones via sret.

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

That is definitely a bug in DMD (swapping `this` and `sret` 
pointers) but doesn't apply to LDC, and is a separate issue.


More information about the Digitalmars-d-learn mailing list