Указатель структуры маршала в VS2010 - PullRequest
2 голосов
/ 08 июня 2010

Мне нужно вызвать C ++ DLL из моей программы на C #. Я пытаюсь сделать это с помощью PInvoke - все отлично работает в VS2005 \ 2008, но после перехода на VS 2010 я получаю следующее исключение:

PInvokeStackImbalance был обнаружен Сообщение: вызов функции PInvoke 'sampleFunc' разбалансировал стек. Это вероятно потому, что удалось PInvoke подпись не соответствует неуправляемая целевая подпись. Проверь это соглашение о вызовах и параметры подписи PInvoke соответствуют целевая неуправляемая подпись.

Это оригинальный прототип C ++:

typedef struct {
    unsigned short field1;
    unsigned short field2;
} sInfo;

_declspec(dllexport) int sampleFunc(sInfo *info, char *txt);

и вот код C #:

[StructLayout(LayoutKind.Sequential)]
    struct SInfo
    {
        //[MarshalAs(UnmanagedType.U1)] //also tried with the MarshalAs attr. Didn't help.
        public ushort field1;
        //[MarshalAs(UnmanagedType.U1)]
        public ushort field2;
    };
[DllImport("sampleModule.dll", CharSet=CharSet.Ansi)]
        public static extern int sampleFunc(ref SInfo info, [MarshalAs(UnmanagedType.LPStr)] string txt);

Я пробовал также с IntPtr вместо ссылки SInfo, но получил тот же результат ...

Любая помощь будет оценена,

Спасибо всем!

Ответы [ 2 ]

2 голосов
/ 08 июня 2010

Трудно понять, как это могло сработать раньше.Объявление C ++ не объявляет соглашение о вызовах, по умолчанию __cdecl, если не переопределено в проекте C ++ с параметром компиляции / Gz.Вы должны сказать маршаллеру P / Invoke:

    [DllImport("sampleModule.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public static extern int sampleFunc(ref SInfo info, string txt);
1 голос
/ 08 июня 2010

Это, вероятно, связано с тем, как вы упаковываете структуру.Размер пакета по умолчанию - 8, так что он, вероятно, думает, что у вас слишком много байтов.Попробуйте установить размер пакета равным 2 (16-битное выравнивание) и посмотрите, поможет ли это:

[StructLayout(LayoutKind.Sequential, Pack=2)]

В качестве альтернативы вы можете указать смещения следующим образом:

[StructLayout(LayoutKind.Explicit)]
public struct struct1
{
   [FieldOffset(0)]
   public ushort a;   // 2 bytes
   [FieldOffset(2)]
   public ushort b;    // 2 bytes
}

Здесь хороший справочник по упаковке

...