外部 C/C++ 库不在 C# 中打印

Posted

技术标签:

【中文标题】外部 C/C++ 库不在 C# 中打印【英文标题】:External C/C++ library not printing in 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 它怎么不能工作?它正在屏幕上打印“某物”。我们在谈论同样的事情吗? 【参考方案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

【讨论】:

以上是关于外部 C/C++ 库不在 C# 中打印的主要内容,如果未能解决你的问题,请参考以下文章

在控制台中打印特殊字符 (C++/C#/SWIG)

我想在 C# 的函数中打印一个随机数组(如果它不在函数中也可以)。我能怎么做? [关闭]

C#上位机开发(十四)—— C#中通过dll库调用外部C/C++函数

C#上位机开发(十四)—— C#中通过dll库调用外部C/C++函数

如何将 iPhone 与外部设备连接?

C# WPF发票打印