无法打印到标准输出

时间:2018-07-18 06:28:27

标签: macos go macos-high-sierra cgo

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

但是我无法将以下程序打印到stdout:

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

它可以正常运行,但不会打印任何内容。上面的代码段主要基于“字符串和事物”代码here

2 个答案:

答案 0 :(得分:1)

尝试一下:

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),该字符串指向一个指向不存在的文件的指针,因为该文件以前没有在任何地方打开或定义。因此,即使程序似乎没有错误地执行,您也看不到任何stdout,因为它已被重定向到不存在的文件中。

此外,应该注意的是,仅将Strings and things部分中的代码放入主程序中而不进行一些自定义是行不通的,因为它是作为博客包提供的,这就是为什么对此感到困惑的原因文件已存在。博客文章中的print包似乎只是假设您尝试向其写入数据流的文件已在先前的某个位置定义。这有点令人困惑,他们应该调整一下。

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

希望即使进行了修改,也可以帮助您完成所需的工作!

答案 1 :(得分:1)

另一个原因可能是由于您的Go程序已链接了C 标准库,但实际上是“标准I / O流”(形式为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*对象 已打开文件的文件描述符, 然后Fd()函数将它从Go的*os.File中拉出来。