www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Small structs: interfacing with C++ potentially broken

reply Jan <Jan Krassnigg.de> writes:
I have a small struct that I'm trying to interface to.

C++
```cpp
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:

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

   static SmallStruct GetValue(float input);
};
```

Then I use it like this:

```cpp
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?
Dec 20 2021
parent reply Tim <tim.dlang t-online.de> writes:
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.
Dec 20 2021
next sibling parent Tejas <notrealemail gmail.com> writes:
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](https://forum.dlang.org/post/capevemlbdanirtcjwfk forum.dlang.org)
Dec 20 2021
prev sibling parent Jan <Jan Krassnigg.de> writes:
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.
Dec 20 2021