Передача структуры из C # в C ++ - PullRequest
9 голосов
/ 08 марта 2011

У меня есть следующая структура в 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 - это 0 в C ++, а не 1, как передано.

Что такоеЯ делаю неправильно?

Правка 1: Я использую Visual Studio 2008 в 32-разрядной версии Windows 7.

Правка 2: Оба sizeof(SnapRoundingOption) возвращают одно и то же число - 16.

Ответы [ 2 ]

14 голосов
/ 08 марта 2011

Проблема в том, как вы распределяете поля 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)]

выровняет две стороны интерфейса.

3 голосов
/ 08 марта 2011

bool является НЕ blittable ! Маршалинг по умолчанию - Win32 BOOL (4 байта), not bool (1 байт)!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...