私は.Net 3.5プロジェクトのstrlen
関数を使用していました。msvcrt.dll
すなわち:
private unsafe static extern int strlen( byte *pByte );
.NET 4.0 に移行した後、この関数を使用するとPInvokeStackImbalance
例外がスローされます。
msvcrt.dll
.NET 3.5 をインポートしたり、この例外を修正するにはどうすればよいですか?
問題は呼び出し規約にあると思われます.Cdeclを使用する必要があります.
[DllImport("msvcrt.dll", CallingConvention=CallingConvention.Cdecl)]
private unsafe static extern int strlen(byte* pByte);
楽しみのために:
public static unsafe int strlen(void* buffer)
{
byte* end = (byte*)buffer;
while (*end++ != 0);
return(int)end - (int)buffer - 1;
}
.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 を呼び出す理由はわかりませんが、もちろん理由があるかもしれません。別の管理された実装が必要な場合は、次の 1 つのライナーを使用できます。
private static int managed_strlen(byte[] bytes)
{
return bytes.TakeWhile(b => b != 0).Count();
}
もちろん、それはマルチバイト (Unicode) 文字を処理しませんが、strlen も処理しないと思います。
これは実際には直接的な答えではありませんが、このような機能については、独自に作成した方がよいようです。たとえば、次の C# コードは動作する可能性があります (ただし、動作する既存の関数を使用するライナーが 1 つある可能性があります)。
static int mystrlen( byte[] pbyte )
{
int i = 0;
while ( pbyte[i] != 0 )
i++;
return i;
}