Search code examples
c#.netpinvoke

"Hello World" via PInvoke


I'm trying to make something in C# that requires calling into some unmanaged DLLs, a process which I know nothing about! I found a "Hello World" tutorial that should be as simple as copying and pasting a couple lines of code from the bottom:

using System;
using System.Runtime.InteropServices;

namespace PInvokeTest
{
    class Program
    {
        [DllImport("msvcrt40.dll")]
        public static extern int printf(string format, __arglist);

        public static void Main()
        {
            printf("Hello %s!\n", __arglist("World"));
            Console.ReadKey();
        }
    }
}

This compiles and runs to completion without any errors, however nothing is printed by the time it gets to the ReadKey().

Did I miss some important setup step? The project builds for .NET 4.6.1 (in case that matters for DLL versioning or something).


Solution

  • The version of msvcrt* you are using is likely the problem. If I create a console app with your unmodified code, I get the same result -- no output.

    If I change the referenced dll from msvcrt40.dll to msvcr120.dll then I see the expected output.

    [DllImport("msvcr120.dll")]
    public static extern int printf(string format, __arglist);
    
    public static void Main()
    {
        printf("Hello %s!\n", __arglist("World"));
        Console.ReadKey();
    }
    

    Additional Information

    The various numbered versions of msvcrt* track the versions of Visual Studio:

    • MSVCRT70.DLL Visual Studio .NET
    • MSVCRT71.DLL Visual Studio 2003
    • MSVCRT80.DLL Visual Studio 2005
    • MSVCRT90.DLL Visual Studio 2008
    • MSVCRT100.DLL Visual Studio 2010
    • MSVCRT110.DLL Visual Studio 2012
    • MSVCRT120.DLL Visual Studio 2013

    This version numbering approach has changed in VS2015 due to the confusion and brittle dependency-chains this creates. More information about these changes can be found here:

    The Great CRT Refactoring

    Introducing the Universal CRT