无法打印到标准输出

Unable to print to stdout

我能够让程序 here 按预期打印 42。

但我无法将以下程序打印到标准输出:

package main

// #include <stdlib.h>
// #include <stdio.h>
import "C"

import (
    "unsafe"
)

func main() {
    cs := C.CString("hello")
    defer C.free(unsafe.Pointer(cs))
    C.fputs(cs, (*C.FILE)(C.stdout))
}

它运行无误,但不打印任何内容。上面的代码片段主要基于 "Strings and things" 代码 here.

试试这个:

package main

// #include <stdlib.h>
// #include <stdio.h>
import "C"
import "unsafe"

func main() {
    cs := C.CString("hello")
    defer C.free(unsafe.Pointer(cs))
    C.puts(cs)
}

解释:

fputs 方法将一个字符串写入数据流,在您的例子中是 stdout,它指向一个指向不存在的文件的指针,因为它之前既没有打开也没有在任何地方定义。因此,即使程序看起来执行无误,您也看不到任何标准输出,因为它被重定向到一个不存在的文件。

此外,应该注意的是,简单地将 Strings and things 部分的代码直接放到主程序中而不进行一些定制是行不通的,因为它在博客中作为一个包提供,这就是为什么有对现有文件的困惑。博客 post 中的 print 包似乎只是假设您尝试写入数据流的文件之前已经在某处定义。这有点令人困惑,他们可能应该对此进行调整。

我用 puts 替换了 fputs 并删除了指向文件的指针,程序执行得很好。

希望即使进行了修改,这也有助于实现您正在寻找的目标!

另一个原因可能是因为你有 C 标准库 链接到你的 Go 程序,但是 "standard I/O streams" (以 FILE*) 是 C 运行时的 属性, 并且必须在使用前对其进行初始化。

对于用 C 编写的典型程序,编译器会创建一个特殊的序言代码,该代码实际上在 C 的 main() 之前运行(通常为此它链接到目标平台的小目标文件标准中,该标准执行必要的东西然后跳转到 main).

据说在 Go 程序中不会发生这种初始化,因此这些标准 I/O 流的高级包装器留下了 未初始化。

您可以通过尝试以下操作来检查这是否属实:

f = fdopen(C.int(os.Stdout.Fd()), C.CString("w"))
C.fputs(cs, f)

看看它是否有效。

fdopen(3) 使 FILE* 对象超出 OS 级别 已打开文件的文件描述符, Fd() 函数从 Go 的 *os.File.

中提取出来