简体   繁体   中英

Passing Structure from C# to C++

I have the following structure in C++:

extern "C" __declspec(dllexport) struct SnapRoundingOption
{
    double PixelSize;
    bool IsISR;
    bool IsOutputInteger;
    int KdTrees;
};

And this is my function declaration in C++:

extern "C" __declspec(dllexport) void FaceGenerationDummy(SnapRoundingOption snapOption);

This is the corresponding C# code:

// I also tried not specifying Pack, but the same error occurred.
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SnapRoundingOption
{
    public  double PixelSize;
    public bool IsISR;
    public bool IsOutputInteger;
    public int KdTrees;

    public SnapRoundingOption(double pixelSize, bool isISR, bool isOutputInt, int kdTrees)
    {
        PixelSize = pixelSize;
        IsISR = isISR;
        IsOutputInteger = isOutputInt;
        KdTrees = kdTrees;
    }
}

[DllImport("Face.dll")]
public static extern void FaceGenerationDummy(SnapRoundingOption snapRoundingOption);

However, when I call the FaceGenerationDummy with this test:

[Test]
public void DummyTest()
{
    SimpleInterop.FaceGenerationDummy(new SnapRoundingOption(10, true, false, 1));
}

I found that KdTrees is 0 in C++, instead of 1 as passed in.

What am I doing wrong?

Edit 1: I am using Visual Studio 2008 on Windows 7 32-bit.

Edit 2: Both sizeof(SnapRoundingOption) return the same number – 16.

The problem here is how you are marshalling the bool fields. These are single bytes in C++ and so need to be marshalled so:

[StructLayout(LayoutKind.Sequential)]
public struct SnapRoundingOption
{
    public double PixelSize;
    [MarshalAs(UnmanagedType.U1)]
    public bool IsISR;
    [MarshalAs(UnmanagedType.U1)]
    public bool IsOutputInteger;
    public int KdTrees;
}

Match this up on the C++ side:

struct SnapRoundingOption
{
    double PixelSize;
    bool IsISR;
    bool IsOutputInteger;
    int KdTrees;
};

I removed the packing settings so that the structures will have alignment natural to the platform.

You should also make sure that your calling conventions agree. As it stands it looks like the C++ code uses cdecl , and the C# code uses stdcall . For example

[DllImport("Face.dll", CallingConvention=CallingConvention.Cdecl)]

would align the two sides of the interface.

bool is NOT blittable ! Its default marshaling is the Win32 BOOL (which is 4 bytes), not bool (which is 1 byte)!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM