通过PInvoke实现"Hello World"

7

我正在尝试在C#中制作一些需要调用未经管理的DLL的东西,这个过程我什么都不知道!我找到了一个“Hello World”教程,应该是从底部复制和粘贴几行代码就可以了:"Hello World" tutorial

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();
        }
    }
}

这段代码可以编译并运行,没有任何错误,但是在执行到 ReadKey() 时没有输出任何内容。

我是否遗漏了一些重要的设置步骤?该项目构建于 .NET 4.6.1(如果对 DLL 版本或其他方面有影响,请注意)。


除非printf自动执行,否则不行。我能从C#刷新吗,还是必须添加另一个PInvoke签名来进行刷新方法?那会是什么样子? - Benjin
1个回答

9
您使用的msvcrt*版本可能是问题所在。如果我使用您未修改的代码创建控制台应用程序,我会得到相同的结果--没有输出。
如果我将引用的dll从msvcrt40.dll更改为msvcr120.dll,那么我就会看到预期的输出。
[DllImport("msvcr120.dll")]
public static extern int printf(string format, __arglist);

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

附加信息

msvcrt* 的各个版本对应着 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

由于这种版本编号方法会导致混乱和脆弱的依赖关系链,因此在 VS2015 中进行了更改。有关这些更改的详细信息,请参见以下链接:

The Great CRT Refactoring

Introducing the Universal CRT


那里缺少了一个 T,为什么会这样? - Camilo Terevinto
2
是的,这很有趣,不是打错了。我认为微软试图确保旧式的8+3字符文件名。 - David Tansey
我刚刚尝试了msvcrt.dll、msvcrt20.dll和msvcrt40.dll与.NET 2.0、3.0、3.5、4.0、4.5、4.5.1、4.5.2和4.6相匹配。没有一个输出符合预期,很多会显示“System.DllNotFoundException”错误。 - Camilo Terevinto
从.NET 2.0开始,无论是32位还是64位,msvcr100.dllmsvcr110.dllmsvcr120.dll都能正常工作。 - Camilo Terevinto
这些数字代表什么?我最初假设是没有“.”的.NET版本,所以我尝试了msvcrt40、45和46.dll,但都没有成功。 - Benjin
@Benjin -- 我编辑了我的答案,包括版本编号方案的一些细节以及它与Visual Studio版本的关系。如果我的答案有助于解决您的问题,请考虑将其标记为已接受。#SOReadyToHelp - David Tansey

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