将结构从C#传递给C ++

时间:2011-03-08 08:40:47

标签: c# c++ interop

我在C ++中有以下结构:

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

这是我在C ++中的函数声明:

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

这是相应的C#代码:

// 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);

但是,当我使用此测试调用FaceGenerationDummy时:

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

我发现KdTrees在C ++中是0,而不是传入的。

我做错了什么?

编辑1:我在Windows 7 32位上使用Visual Studio 2008。

编辑2:两个sizeof(SnapRoundingOption)都返回相同的数字 - 16.

2 个答案:

答案 0 :(得分:14)

这里的问题是你如何编组bool字段。这些是C ++中的单个字节,因此需要编组,因此:

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

在C ++方面进行匹配:

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

我删除了打包设置,以使结构与平台保持自然对齐。

您还应该确保您的通话约定一致。目前看来,C ++代码使用cdecl,而C#代码使用stdcall。例如

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

将对齐界面的两侧。

答案 1 :(得分:3)

bool is NOT blittable!它的默认编组是Win32 BOOL(4个字节),不是 bool(1个字节)!