Thread overview
Small structs: interfacing with C++ potentially broken
Dec 20, 2021
Jan
Dec 20, 2021
Tim
Dec 20, 2021
Tejas
Dec 20, 2021
Jan
December 20, 2021

I have a small struct that I'm trying to interface to.

C++

struct __declspec(dllexport) SmallStruct
{
  float value = 0;
  //float value2 = 0;
  //float value3 = 0;

  SmallStruct(float val)
    : value(val)
  {
  }

  static SmallStruct GetValue(float input)
  {
    return SmallStruct(input * 3.141f);
  }
};

And on the D side:

extern(C++) struct SmallStruct
{
  float value = 0;
//   float value2 = 0;
//   float value3 = 0;

  static SmallStruct GetValue(float input);
};

Then I use it like this:

SmallStruct s = SmallStruct.GetValue(3);

Running this crashes on the C++ side, with an access violation writing data.
Looking at the disassembly, it seems that C++ expects the Smallstruct return object to be passed in, whereas D assumes that the SmallStruct is passed through registers.

This is with MVSC 2019 compiled for x64 and DMD v2.098.0.

If I enable 'value2' and 'value3', it seems that both compilers start to agree on the calling convention.

Is this a known issue, or is there a way to instruct DMD to use a specific calling convention for a given type?

December 20, 2021

On Monday, 20 December 2021 at 10:24:00 UTC, Jan wrote:

>

Is this a known issue, or is there a way to instruct DMD to use a specific calling convention for a given type?

This looks like a bug. It seems to work without constructor in C++, but still crashes with a constructor in D. It also seems to work if a trivial destructor is added in D: ~this(){}

This could be related to POD types in C++. Structs with constructor or destructor are probably passed differently, but dmd only looks at the destructor.

December 20, 2021

On Monday, 20 December 2021 at 11:58:03 UTC, Tim wrote:

>

On Monday, 20 December 2021 at 10:24:00 UTC, Jan wrote:

>

Is this a known issue, or is there a way to instruct DMD to use a specific calling convention for a given type?

This looks like a bug. It seems to work without constructor in C++, but still crashes with a constructor in D. It also seems to work if a trivial destructor is added in D: ~this(){}

This could be related to POD types in C++. Structs with constructor or destructor are probably passed differently, but dmd only looks at the destructor.

I think it's got something to do with this

December 20, 2021

On Monday, 20 December 2021 at 11:58:03 UTC, Tim wrote:

>

On Monday, 20 December 2021 at 10:24:00 UTC, Jan wrote:

>

Is this a known issue, or is there a way to instruct DMD to use a specific calling convention for a given type?

This looks like a bug. It seems to work without constructor in C++, but still crashes with a constructor in D. It also seems to work if a trivial destructor is added in D: ~this(){}

This could be related to POD types in C++. Structs with constructor or destructor are probably passed differently, but dmd only looks at the destructor.

Well, that at least gives me a way to work around this issue.