Access C stdout in Julia

I am trying to write a wrapper for an external library(GraphBLAS). One of the matrix print functions expects a FILE* pointer in its arguments so I tried this

ccall(dlsym(hdl, "GxB_Matrix_fprint"), Cint, (GrB_Matrix, Ptr{UInt8}, Cint, Ptr{Nothing}), X, xname, 3, cglobal(:stdout))

but I get a segmentation fault -

signal (11): Segmentation fault
in expression starting at no file:0
_IO_vfprintf_internal at /build/glibc-LK5gWL/glibc-2.23/stdio-common/vfprintf.c:1320

What is the right way to read stdout ?

This seems to work, though I can’t claim that it’s the best way to do it.

stdoutfd = 1; # or Base._fd(stdout)
fd = ccall(:dup, Cint, (Cint,), stdoutfd)
FILE = ccall(:fdopen, Ptr{Cvoid}, (Cint, Cstring), fd, "w")
ccall(:fprintf, Cint, (Ptr{Cvoid}, Cstring, Cint), FILE, "Test %i\n", 1);
ccall(:fclose, Cint, (Ptr{Cvoid},), FILE)
1 Like

cglobal returns the address of the variable and you need to load it.

1 Like

You can also use Libc.FILE(io) to convert a Julia io stream to a FILE* for passing to C code. Unfortunately, it doesn’t work with stdout, but you can use the fact that C’s stdout corresponds to the file descriptor 1 to construct a RawFD object and from this construct a FILE*:

julia> so = Libc.FILE(Libc.RawFD(1), "w")  # corresponds to C standard output
Base.Libc.FILE(Ptr{Nothing} @0x00007fff947df0c8)

julia> ccall(:fprintf, Cint, (Ptr{Cvoid}, Cstring), so, "Hello world!\n")
Hello world!
13
6 Likes

Thank you everyone !