Skip to content

Commit

Permalink
make Cstring more usable as a return value (see JuliaLang#10799)
Browse files Browse the repository at this point in the history
  • Loading branch information
stevengj committed Sep 1, 2015
1 parent 4e44a1c commit 8cc7013
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 2 deletions.
5 changes: 5 additions & 0 deletions base/c.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ end

convert{T<:Union{Int8,UInt8}}(::Type{Cstring}, p::Ptr{T}) = box(Cstring, unbox(Ptr{T}, p))
convert(::Type{Cwstring}, p::Ptr{Cwchar_t}) = box(Cwstring, unbox(Ptr{Cwchar_t}, p))
convert{T<:Union{Int8,UInt8}}(::Type{Ptr{T}}, p::Cstring) = box(Ptr{T}, unbox(Cstring, p))
convert(::Type{Ptr{Cwchar_t}}, p::Cwstring) = box(Ptr{Cwchar_t}, unbox(Cwstring, p))

# here, not in pointer.jl, to avoid bootstrapping problems in coreimg.jl
pointer_to_string(p::Cstring, own::Bool=false) = pointer_to_string(convert(Ptr{UInt8}, p), own)

# convert strings to ByteString etc. to pass as pointers
cconvert(::Type{Cstring}, s::AbstractString) = bytestring(s)
Expand Down
2 changes: 2 additions & 0 deletions base/libc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -194,5 +194,7 @@ free(p::Ptr) = ccall(:free, Void, (Ptr{Void},), p)
malloc(size::Integer) = ccall(:malloc, Ptr{Void}, (Csize_t,), size)
realloc(p::Ptr, size::Integer) = ccall(:realloc, Ptr{Void}, (Ptr{Void}, Csize_t), p, size)
calloc(num::Integer, size::Integer) = ccall(:calloc, Ptr{Void}, (Csize_t, Csize_t), num, size)
free(p::Cstring) = free(convert(Ptr{UInt8}, p))
free(p::Cwstring) = free(convert(Ptr{Cwchar_t}, p))

end # module
2 changes: 1 addition & 1 deletion base/strings/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function bytestring(p::Union{Ptr{UInt8},Ptr{Int8}})
p == C_NULL ? throw(ArgumentError("cannot convert NULL to string")) :
ccall(:jl_cstr_to_string, Any, (Ptr{UInt8},), p)::ByteString
end
bytestring(s::Cstring) = bytestring(box(Ptr{Cchar}, unbox(Cstring,s)))
bytestring(s::Cstring) = bytestring(convert(Ptr{UInt8}, s))

function bytestring(p::Union{Ptr{UInt8},Ptr{Int8}},len::Integer)
p == C_NULL ? throw(ArgumentError("cannot convert NULL to string")) :
Expand Down
2 changes: 1 addition & 1 deletion base/unicode/utf32.jl
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ elseif sizeof(Cwchar_t) == 4
const WString = UTF32String
const wstring = utf32
end
wstring(s::Cwstring) = wstring(box(Ptr{Cwchar_t}, unbox(Cwstring,s)))
wstring(s::Cwstring) = wstring(convert(Ptr{Cwchar_t}, s))

# Cwstring is defined in c.jl, but conversion needs to be defined here
# to have WString
Expand Down
10 changes: 10 additions & 0 deletions test/strings/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,16 @@ let s = "ba\0d"
@test_throws ArgumentError Base.unsafe_convert(Cwstring, wstring(s))
end

cstrdup(s) = @windows? ccall(:_strdup, Cstring, (Cstring,), s) : ccall(:strdup, Cstring, (Cstring,), s)
let p = cstrdup("hello")
@test bytestring(p) == "hello" == pointer_to_string(cstrdup(p), true)
Libc.free(p)
end
let p = @windows? ccall(:_wcsdup, Cwstring, (Cwstring,), "tést") : ccall(:wcsdup, Cwstring, (Cwstring,), "tést")
@test wstring(p) == "tést"
Libc.free(p)
end

# issue # 11389: Vector{UInt32} was copied with UTF32String, unlike Vector{Char}
a = UInt32[48,0]
b = UTF32String(a)
Expand Down

0 comments on commit 8cc7013

Please sign in to comment.