I'm able to get the program here to print 42 as expected.
But I am unable to get the following program to print to 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))
}
It runs without error, but it doesn't print anything. The above snippet is mostly based off the "Strings and things" code here.
Try this:
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)
}
Explanation:
The fputs
method writes a string to a data stream, in your case stdout, which is directed towards a pointer to a file that doesn't exist because it has neither been opened nor defined anywhere previously. So even though the program appears to execute without error, you aren't seeing any of the stdout because it is being redirected to a nonexistent file.
Further, it should be noted that simply dropping the code from the Strings and things section into a main program without some customization would not work because it is provided in the blog as a package, which is why there was confusion about the file existing. It seems that the print
package from the blog post simply assumes the file you are attempting to write the data stream to has already been defined somewhere previously. It's a little confusing and they should probably adjust that.
I replaced fputs
with puts
as well as removed the pointer to the file and the program executes just fine.
Hope that even with the modifications this helps accomplish what you are looking for!
Another cause might be due to the fact you have the C standard library linked with your Go program, but the "standard I/O streams" (in the form of FILE*
) is a property of the C runtime, and they have to be initialized before use.
For a typical program written in C, the compiler creates a special prologue code which actually runs before C's main()
(usually to do that it links in a small object file standard for the target platform which does the necessary stuff and then jumps to main
).
Supposedly in a Go program such initialization does not happen and so these high-level wrappers for the standard I/O streams left uninitialized.
You might check if this is true by trying something like this:
f = fdopen(C.int(os.Stdout.Fd()), C.CString("w"))
C.fputs(cs, f)
and see if it works.
The fdopen(3)
makes a FILE*
object out of an OS-level file descriptor for an already opened file, and the Fd()
function pulls just that out of a Go's *os.File
.