11

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.

11
  • 1
    Are you sure the packing alignment is also 1 in C++? Commented Mar 8, 2011 at 8:43
  • I tried both, specify Pack and don't specify Pack, none which worked. Commented Mar 8, 2011 at 8:45
  • @Graviton: Also, does your C++ compiler consider int to be 32 bits wide? Commented Mar 8, 2011 at 8:45
  • 2
    @Graviton: Ooooh... where's the word "struct" for your struct? Is that a typo or is it actually what you wrote?! Commented Mar 8, 2011 at 8:47
  • 1
    Check out the memory representation of your structure in C++ and use the proper Pack and MarshalAs attributes/parameters. Commented Mar 8, 2011 at 8:48

2 Answers 2

20

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.

Sign up to request clarification or add additional context in comments.

10 Comments

@mehrdad Thanks, I like these P/Invoke questions!
@David: Ditto... they make me think harder. :) (I especially like the COM interface questions... those can get really tricky!)
@Graviton Why didn't you do the C++ part as well? It matters! Anyway, I wrote a test for this and successfully passed this struct in both directions.
@David: That's what I suggested 40 minutes ago in my comment :-P. @Graviton: packing alignment should be the same for you in both C++ and C#. It should work with Pack=0 or without it.
@David: are you sure about WinAPI using packing alignment 1? MS recommends using the default packing (8) so datatypes are aligned according to their size. Also I have only seen MS using pack=1 for arrays (internally generated)... @Graviton: msdn.microsoft.com/en-us/library/2e70t5y1.aspx
|
5

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

1 Comment

+1: Since you stated what bool is marshaled to (A point David Heffernan forgot in his answer :-) )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.