在.Net 4中:PInvokeStackImbalance异常

4
我曾在.NET 3.5项目中使用msvcrt.dll的strlen函数。具体来说是这样的:private unsafe static extern int strlen( byte *pByte );。但是在迁移到.NET 4.0后,如果我继续使用该函数,则会抛出PInvokeStackImbalance异常。请问如何导入.NET 3.5的msvcrt.dll或修复此异常?
4个回答

12

我怀疑问题出在调用约定上,你应该使用Cdecl。

[DllImport("msvcrt.dll", CallingConvention=CallingConvention.Cdecl)]
private unsafe static extern int strlen(byte* pByte);

+1 我今天在工作中遇到了同样的问题,你的解决方案正是我所需要的。谢谢你。 - Robert Greiner

1

这并不是直接的答案,但对于像这样的功能,最好还是自己编写。例如,以下C#代码可能会起作用(尽管可能存在使用现有函数的一行代码也可以实现的情况):

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

1

从 .NET 3.5 到 4 中,不应该有任何更改。(而且,顺便说一下,msvcrt.dll 并不是框架的一部分 - 它是微软 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();
}

当然,这并不涉及多字节(Unicode)字符,但我认为strlen也不涉及。


嗨Driis,感谢您的回复。我正在不安全代码中使用它,我忘了提到这一点。我忘记了@ChrisTaylor:P所提到的CallingConvention属性。 - SDReyes

1

只是为了好玩:

public static unsafe int strlen(void* buffer)
{
    byte* end = (byte*)buffer;
    while (*end++ != 0);
    return(int)end - (int)buffer - 1;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接