При вызове DLL из C #, почему небольшие структуры неправильно выравнивают параметры функции? - PullRequest
2 голосов
/ 21 марта 2011

Я пишу приложение ac # / c ++, у которого возникли проблемы, когда я попытался передать структуру, содержащую только два числа с плавающей точкой.Например:

[DllImport("Resources\\CppInterface", EntryPoint = "?ReadDllTest@ScriptParserInterface@@YA?AVDllTest@@PAVScriptParser@@PB_W@Z", CharSet = CharSet.Unicode)]
private static extern DllTest ReadDllTestS(IntPtr scriptParser, string name);

Отлично работает, когда DLLTest содержит 3 или 4 числа с плавающей запятой.Однако, когда он содержит 2, intptr и пропущенный через него указатель на строку заканчиваются на 1 байт со смещением на стороне C ++.

Есть идеи, что может вызвать это?

Пример структуры структуры:

[StructLayout( LayoutKind.Sequential )]
public struct DllTest
{
    public float a, b;/*, c, d; (works if c or/d are in)*/

    DllTest( float i, float j )
    {
        a = i;
        b = j;
    }
}

C ++ сторона:

DllTest ScriptParserInterface::ReadDllTest( ScriptParser* scriptParser, const wchar_t* name )
{
     return DllTest(); /* If only using two variables in DLLTest. scriptParser and name no longer work, but are located at *((&scriptParser)-1) and *((&name)-1)
}

Любые предложения будут очень признательны.Спасибо.

1 Ответ

2 голосов
/ 22 марта 2011

ScriptParserInterface должен быть именем пространства имен, вы никогда не заставите его работать, если это имя класса.Функция __cdecl в соответствии с искаженным именем, вы забыли использовать свойство CallingConvention в объявлении [DllImport].Вы должны были получить предупреждение MDA PInvokeStackImbalance.Поскольку вы этого не сделали, я должен предположить, что вы запускаете это как 64-битный код.

Забвение CallingConvention само по себе может быть достаточным, чтобы отбросить стек.Начни там.

...