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.

Reply via email to