How to create a Cstring from a String?

How do you want to manage the memory for this? If Julia allocates a String object and returns a pointer to the data to C (which is possible via unsafe_convert), then the C code could crash if Julia garbage-collects the String before the C pointer is used (hence the “unsafe”). If you are okay with this — if you know for certain that the Julia string will not be garbage-collected before you use it (e.g. because you hold onto a reference to it), then you can call Base.unsafe_convert(Cstring, s) on s::String.

If C expects a malloc-ed string that C will take responsibility to free, then you’ll need to explicitly call malloc and copy the data yourself. e.g.

function malloc_cstring(s::String)
    n = sizeof(s)+1 # size in bytes + NUL terminator
    return GC.@preserve s @ccall memcpy(Libc.malloc(n)::Cstring,
                                        s::Cstring, n::Csize_t)::Cstring
end

Conversely, when you declare an argument of a ccall as a Cstring (as is done in the call to memcpy here), then Julia can simply pass a pointer to the string data (assuming the data only needs to stick around for the duration of the ccall), first checking that the string contains no NUL bytes (as otherwise NUL-termination will not work; internally, Julia String data is already NUL-terminated so that it can be passed to C functions without copying).

2 Likes