【问题标题】:External C/C++ library not printing in C#外部 C/C++ 库不在 C# 中打印
【发布时间】:2016-07-21 10:08:09
【问题描述】:

我正在从 C# 调用 C++ 外部库。返回有效,但是printf() 不在控制台窗口中打印数据。为什么会这样?我做错了吗?

即使我调用 DisplayHelloFromDLL 而不将其返回值分配给变量 x,打印的文本也不会显示在屏幕上。

C++:

#include <stdio.h> 

extern "C"
{
__declspec(dllexport) char * DisplayHelloFromDLL()
 {
     printf ("Hello from DLL !\n");
     return "Something";

 }
}

C#:

using System;
using System.Runtime.InteropServices;



class HelloWorld
{

    [DllImport("Hello.dll", EntryPoint = "DisplayHelloFromDLL")]
    public static extern string DisplayHelloFromDLL();

    static void Main()
    {
        Console.WriteLine("This is C# program");
        string x = DisplayHelloFromDLL();
        Console.WriteLine(x);
        Console.ReadKey();
    }

}

【问题讨论】:

  • 没有显示 C 代码。你的意思是 C++。
  • 是的,抱歉,我将编辑问题。但是,我不明白为什么有人反对它。
  • 您在 C# 端以这种方式处理 char* 返回类型。您的代码尝试释放调用CoTaskMemFree 的指针。将返回类型声明为IntPtr,得到一个带有Marshal.PtrToStringAnsi的字符串。
  • @DavidHeffernan 实际上返回数据效果很好。但是 C 中的 'printf()' 不会在控制台中打印“Hello from DLL”。
  • @DavidHeffernan 它怎么不能工作?它正在屏幕上打印“某物”。我们在谈论同样的事情吗?

标签: c# c++ dll pinvoke


【解决方案1】:

根据此线程 (https://social.msdn.microsoft.com/Forums/en-US/5da6cdb2-bc2b-4fff-8adf-752b32143dae/printf-from-dll-in-console-app-in-visual-studio-c-2010-express-does-not-output-to-console-window?forum=Vsexpressvcs),调试时存在的 Visual Studio 托管进程是 DLL 的控制台输出无法到达您的控制台的原因。

检查这一点的一种简单方法是直接运行可执行文件,而不是通过 IDE 的调试器。如果确实确认是这种情况,那么您可以根据需要禁用托管进程,如链接线程中所述。

您的代码还有另外几个问题:

[DllImport("Hello.dll", EntryPoint = "DisplayHelloFromDLL")]
public static extern string DisplayHelloFromDLL();

默认的 p/invoke 调用约定是 stdcall,但默认的 C++ 调用约定是 cdecl。因此,您的 C# p/invoke 使用了错误的调用约定。您将需要更改其中一个声明来解决此问题。

并且将返回类型声明为string 意味着编组器将尝试通过调用CoTaskMemFree 来释放返回的指针。 C 字符串未分配CoTaskMemAlloc,因此这是未定义的行为。您应该将返回类型声明为IntPtr 并使用Marshal.PtrToStringAnsi 来获取字符串,记住C++ 代码返回的文字不应(实际上不能)被释放。或者,使用其他各种方法中的一种来返回一个字符串,这在确定内存所有权的方式上可能更清晰一些。

【讨论】:

  • 实际上这有帮助:“检查这一点的一种简单方法是直接运行可执行文件,而不是通过 IDE 的调试器。如果确实确认是这种情况,那么您可以禁用托管进程,如果您希望,如链接线程中所述。”。它可以工作,但是我必须从其他 cmd 窗口启动这个应用程序。
【解决方案2】:

我认为,您的问题是 DLL 没有分配给它的控制台 - 它不应该知道 C#-Console。也许,您可以尝试将对您的 C#-Console-Object 的引用传递给您的“DisplayHelloFromDLL”-Function。 但我从未尝试过 - 我不知道如何从 C/C++ DLL 访问/使用 C#-Console-Object。

【讨论】:

    【解决方案3】:

    您的 C 外部库可能无法访问任何输出控制台。您可以使用以下函数写入输出控制台。

    AllocConsole

    GetSTDHandle

    WriteConsole

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-03
      • 1970-01-01
      • 2018-07-10
      • 1970-01-01
      • 2019-06-19
      • 2010-09-30
      • 2019-07-31
      • 2014-07-23
      相关资源
      最近更新 更多