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

External C/C++ library not printing in C#

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

即使我调用 DisplayHelloFromDLL 而没有将其 return 分配给变量 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();
    }

}

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

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

AllocConsole

GetSTDHandle

WriteConsole

根据此线程 (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 使用了错误的调用约定。您需要更改其中一项声明才能解决此问题。

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