в .Net 4: исключение PInvokeStackImbalance - PullRequest
3 голосов
/ 27 апреля 2010

Я использовал функцию strlen из msvcrt.dll в проекте .Net 3.5. Более конкретно:

private unsafe static extern int strlen( byte *pByte );

После перехода на .NET 4.0, если я использую эту функцию, выдается исключение PInvokeStackImbalance.

Как я могу импортировать .NET 3.5 msvcrt.dll или исправить это исключение?

Ответы [ 4 ]

11 голосов
/ 27 апреля 2010

Я подозреваю, что проблема в соглашении о вызовах, вы должны использовать Cdecl.

[DllImport("msvcrt.dll", CallingConvention=CallingConvention.Cdecl)]
private unsafe static extern int strlen(byte* pByte);
1 голос
/ 27 апреля 2010

Просто для удовольствия:

public static unsafe int strlen(void* buffer)
{
    byte* end = (byte*)buffer;
    while (*end++ != 0);
    return(int)end - (int)buffer - 1;
}
1 голос
/ 27 апреля 2010

Здесь не должно быть никаких изменений с .NET 3.5 до 4. (и, между прочим, msvcrt.dll не является частью платформы - это библиотека времени выполнения Microsft C ++). Вы уверены, что больше ничего не изменилось в вашем проекте.

Я только что попробовал этот код, который работает и печатает «4», как и ожидалось:

class Test
{
    public unsafe static void Main(string[] args)
    {
        byte[] bytes = new byte[] {70, 40, 30, 51, 0};
        fixed(byte* ptr = bytes)
        {
            int len = strlen(ptr);
            Console.WriteLine(len);
        }
    }
    [DllImport("msvcrt.dll")]
    private unsafe static extern int strlen(byte* pByte);       
}

Мне неясно, почему вы хотите вызывать strlen из управляемого кода, но, конечно, у вас могут быть свои причины. Если вам нужна альтернативная управляемая реализация, вот один вкладыш, который вы можете использовать:

private static int managed_strlen(byte[] bytes)
{
    return bytes.TakeWhile(b => b != 0).Count();
}

Конечно, это не относится к многобайтовым (юникодным) символам, но я не думаю, что strlen тоже.

1 голос
/ 27 апреля 2010

Это не совсем прямой ответ, но кажется, что для чего-то вроде этой функциональности, может быть, лучше написать свой собственный. Например, следующий код на C # может работать (хотя, возможно, есть и один лайнер, использующий существующие функции, которые тоже будут работать):

  static int mystrlen( byte[] pbyte )
     {
     int i = 0;
     while ( pbyte[i] != 0 )
        i++;
     return i;
     }
...