How wrapp strcpy libc


#1

How wrapp strcpy of libc which ccall, this does not work for me

to=Ref{Cstring}()
ccall(:strcpy, Ptr{UInt8}, (Ref{Cstring}, Ptr{UInt8}), to, "Hello")
unsafe_string(to)

#2

The issue with your example is that you are not allocating any memory for the destination pointer. Ref{Cstring}() is an empty string. Technically what you want to do is possible in Julia, but it is risky even for expert C developers. See pointer or Libc.malloc depending on whether the memory needs to be owned by Julia. Please carefully read the “Calling C” section of the manual, especially this and the following section:

https://docs.julialang.org/en/latest/manual/calling-c-and-fortran-code/#Memory-Ownership-1


#3

Maybe you could explain what you’re trying to achieve? There’s probably an easier way of doing it.


#4

Just to learn, this works for me

function test(s)
    to = Ptr{UInt8}(Libc.malloc(length(s)*sizeof(Char)))
    ccall(:strcpy, Ptr{UInt8}, (Ptr{UInt8}, Ptr{UInt8}), to, s)
    str = unsafe_string(to)
    Libc.free(to)
    str
end

julia> test("Hello World!")

Thank you


#5

Why would you want to do this?


#6

It’s not at all I’m just trying to learn how to use ccall, with examples of libc

Sorry for my English, I’m Spanish


#7

Is there any downsides to using an array to allocate memory instead of malloc ?

to = Array{UInt8}(sizeof(s))

#8

It’s unclear what you’re trying to do, but this code is wrong; I’ve added comments inline to indicate possible corrections:

function test(s)
    to = Ptr{UInt8}(Libc.malloc(length(s)*sizeof(Char)))
      # should allocate `sizeof(s)` bytes
    ccall(:strcpy, Ptr{UInt8}, (Ptr{UInt8}, Ptr{UInt8}), to, s)
      # the use of strcpy in C should be avoided, use memmove instea
      # if you must deal with a poorly-designed C-api that uses `char*` without a size/length argument,
      # be sure to mark the types as `Cstring` in the `ccall` so they are null-terminated by Julia
    str = unsafe_string(to)
      # could just replace this function with `return s` :P 
    Libc.free(to)
      # its often recommended to wrap the usage in try/finally
      # so that error don't leak memory (or use Array allocation as suggested by jonathanBieler)
    return str
end