在c#中使用pinvoke来调用64位的sprintf和朋友

Wil*_*ean 2 c# 64-bit pinvoke

我在C#中使用pinvoke调用_snwprintf时遇到了一个有趣的问题.它适用于整数类型,但不适用于浮点数.

这是在64位Windows上,它在32位上运行良好.

我的代码如下,请记住,这是一个人为的例子来展示我所看到的行为.

class Program
{
    [DllImport("msvcrt.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
    private static extern int _snwprintf([MarshalAs(UnmanagedType.LPWStr)] StringBuilder str, IntPtr length, String format, int p);

    [DllImport("msvcrt.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
    private static extern int _snwprintf([MarshalAs(UnmanagedType.LPWStr)] StringBuilder str, IntPtr length, String format, double p);

    static void Main(string[] args)
    {
        Double d = 1.0f;
        Int32 i = 1;
        Object o = (object)d;
        StringBuilder str = new StringBuilder(32);

        _snwprintf(str, (IntPtr)str.Capacity, "%10.1lf", (Double)o);
        Console.WriteLine(str.ToString());

        o = (object)i;
        _snwprintf(str, (IntPtr)str.Capacity, "%10d", (Int32)o);
        Console.WriteLine(str.ToString());

        Console.ReadKey();
    }
}
Run Code Online (Sandbox Code Playgroud)

这个程序的输出是

   0.0
     1
Run Code Online (Sandbox Code Playgroud)

它应该在第一行打印1.0而不是0.0,到目前为止我很难过.

Ree*_*sey 6

我不确定为什么你的调用不起作用,但这些方法安全版本在x86和x64中都能正常工作.

以下代码可以正常工作,如预期的那样:

class Program
{
    [DllImport("msvcrt.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
    private static extern int _snwprintf_s([MarshalAs(UnmanagedType.LPWStr)] StringBuilder str, IntPtr bufferSize, IntPtr length, String format, int p);

    [DllImport("msvcrt.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
    private static extern int _snwprintf_s([MarshalAs(UnmanagedType.LPWStr)] StringBuilder str, IntPtr bufferSize, IntPtr length, String format, double p);

    static void Main(string[] args)
    {
        // Preallocate this to a given length
        StringBuilder str = new StringBuilder(100);
        double d = 1.4;
        int i = 7;
        float s = 1.1f;

        // No need for box/unbox
        _snwprintf_s(str, (IntPtr)100, (IntPtr)32, "%10.1lf", d);
        Console.WriteLine(str.ToString());

        _snwprintf_s(str, (IntPtr)100, (IntPtr)32, "%10.1f", s);
        Console.WriteLine(str.ToString());

        _snwprintf_s(str, (IntPtr)100, (IntPtr)32, "%10d", i);
        Console.WriteLine(str.ToString());

        Console.ReadKey();
    }
}
Run Code Online (Sandbox Code Playgroud)