Suppose I have the following 2 C++ structs:
struct UsbErrorCodes
{
const signed int UsbInterfaceErrorCode = 0;
const DWORD WinDriverErrorCode = 0;
UsbErrorCodes(const signed int usbInterfaceErrorCode, const DWORD winDriverErrorCode)
: UsbInterfaceErrorCode(usbInterfaceErrorCode),
WinDriverErrorCode(winDriverErrorCode)
{
}
};
struct NativeReadBytesResponse
{
const unsigned long NumberOfBytesRead = 0;
const UsbErrorCodes UsbErrorCodes;
NativeReadBytesResponse(const unsigned long numberOfBytesRead, const ::UsbErrorCodes usbErrorCodes)
: NumberOfBytesRead(numberOfBytesRead),
UsbErrorCodes(usbErrorCodes)
{
}
};
And I have a C++ function returning a NativeReadBytesResponse
:
NativeReadBytesResponse ReadBytes
(
unsigned long numberOfBytesToRead,
unsigned char* bytesBuffer,
unsigned long transferTimeout = 3000
);
How do I setup a C# method to call that function and get me back that NativeReadBytesResponse
?
I have tried this but get a Managed Debugging Assistant 'PInvokeStackImbalance'
exception when it's called.
[DllImport("MyNativeLibrary.dll", CallingConvention = CallingConvention.StdCall)]
private static extern NativeReadBytesResponse ReadBytes
(
uint numberOfBytesToRead,
[Out]
out byte[] bytesBuffer,
uint transferTimeout = 3000
);
I should also note that I have been able to return UsbErrorCodes
from C++ to its C# equivalent struct by mimicing the struct in C# and adding [StructLayout(LayoutKind.Sequential, Size = 64)]
on top of the struct. Here are the 2 C# structs which the 2 C++ structs should map to:
[StructLayout(LayoutKind.Sequential, Size = 64)]
public partial struct UsbErrorCodes : IEquatable<UsbErrorCodes>
{
public static bool operator ==(UsbErrorCodes left, UsbErrorCodes right)
=> left.Equals(right);
public static bool operator !=(UsbErrorCodes left, UsbErrorCodes right)
=> !left.Equals(right);
[DisplayName("USB Interface Error Code")]
public uint UsbInterfaceErrorCode { get; }
[DisplayName("Windows Driver Error Code")]
public WinDriverError WinDriverErrorCode { get; }
[Newtonsoft.Json.JsonConstructor]
public UsbErrorCodes
(
uint usbInterfaceErrorCode,
WinDriverError winDriverErrorCode
)
{
UsbInterfaceErrorCode = usbInterfaceErrorCode;
WinDriverErrorCode = winDriverErrorCode;
}
public bool Equals(UsbErrorCodes other)
=> UsbInterfaceErrorCode.Equals(other.UsbInterfaceErrorCode)
&& WinDriverErrorCode.Equals(other.WinDriverErrorCode);
public override bool Equals(object obj)
=> obj is UsbErrorCodes usbErrorCodes
? Equals(usbErrorCodes)
: base.Equals(obj);
public override int GetHashCode()
=> UsbInterfaceErrorCode.GetHashCode()
^ WinDriverErrorCode.GetHashCode();
}
[StructLayout(LayoutKind.Sequential, Size = 96)]
public struct NativeReadBytesResponse : IEquatable<NativeReadBytesResponse>
{
public static bool operator ==(NativeReadBytesResponse left, NativeReadBytesResponse right)
=> left.Equals(right);
public static bool operator !=(NativeReadBytesResponse left, NativeReadBytesResponse right)
=> !left.Equals(right);
public uint NumberOfBytesRead { get; }
[DisplayName("USB Error Codes")]
public UsbErrorCodes UsbErrorCodes { get; }
[Newtonsoft.Json.JsonConstructor]
public NativeReadBytesResponse
(
uint numberOfBytesRead,
UsbErrorCodes usbErrorCodes
)
{
NumberOfBytesRead = numberOfBytesRead;
UsbErrorCodes = usbErrorCodes;
}
public bool Equals(NativeReadBytesResponse other)
=> NumberOfBytesRead.Equals(other.NumberOfBytesRead)
&& UsbErrorCodes.Equals(other.UsbErrorCodes);
public override bool Equals(object obj)
=> obj is NativeReadBytesResponse nativeReadBytesResponse
? Equals(nativeReadBytesResponse)
: base.Equals(obj);
public override int GetHashCode()
=> NumberOfBytesRead.GetHashCode()
^ UsbErrorCodes.GetHashCode();
}
Does C#-to-C++-to-C# interop not support objects nested within objects or is something else at fault here?
question from:
https://stackoverflow.com/questions/65598933/is-there-a-way-to-pass-a-c-struct-containing-another-c-struct-back-to-c 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…