"Hello World" via PInvoke
Asked Answered
N

1

7

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).

Nonentity answered 16/12, 2015 at 1:54 Comment(1)
Unless printf does that automatically, then no. Can I flush from C#, or do I have to add another PInvoke signature for a flush method? What would that look like?Nonentity
C
9

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

Consumer answered 16/12, 2015 at 2:6 Comment(6)
There is a missing T in there, why is this?Mariquilla
Yeah that's interesting isn't it. It is not a typo though. I think MS was trying to ensure old-style 8 + 3 character file names.Consumer
I have just tried msvcrt.dll, msvcrt20.dll and msvcrt40.dll against .NET 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2 and 4.6. None give the expected output and a lot give a System.DllNotFoundExceptionMariquilla
From .NET 2.0 onward, both 32 and 64 bit, msvcr100.dlll msvcr110.dll and msvcr120.dll work correctly.Mariquilla
What do these numbers represent? I'd originally assumed .NET version without the '.', so I'd tried msvcrt40, 45, and 46.dll to no success.Nonentity
@Nonentity -- I edited my answer to include some detail about the version numbering scheme and the way it relates to Visual Studio versions. If my answer helped to solve your problem please consider marking it as Accepted. #SOReadyToHelpConsumer

© 2022 - 2024 — McMap. All rights reserved.