# Formatting/converting Matrix{Char} into Vector{String}

**URL:** <https://discourse.julialang.org/t/formatting-converting-matrix-char-into-vector-string/79224>\
**Category:** New to Julia\
**Tags:** ccall, strings, arrays, char\
**Created:** [April 8, 2022, 1:43pm UTC](https://discourse.julialang.org/t/formatting-converting-matrix-char-into-vector-string/79224 "2022-04-08T13:43:58Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![gltchr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gltchr/32/35322_2.png) [@gltchr](https://discourse.julialang.org/u/gltchr)\
**Post date:** [April 8, 2022, 1:43pm UTC](https://discourse.julialang.org/t/formatting-converting-matrix-char-into-vector-string/79224/1 "2022-04-08T13:43:58Z")

</div>

Hello, I am writing some simple wrappers around an old C library.  
I am new to Julia and absolutely new to C, so it might be something obvious.  
I have managed to get majority of functions working, but I am unsure about the handling of returned Cchar matrices.  
Here is an example:

```julia
##C-call:
# int list_of_signals(int *, int *, char *, int *)
# char list[24*N]
# int ierr, id, ndim, status
# status = listas_(&id, &ndim, &num_of_sigs, list, &ierr)

```

Function is supposed to return first _num\_of\_sigs_ signals in a list corresponding to a given id.

```julia
function list(id::Int, num_of_sigs::Int)

	ier=Ref{Cint}(0);
	ID=Ref{Cint}(id);
	NSIG=Ref{Cint}(num_of_sigs);
	list=Array{Cchar}(undef,24,n_dim);

	status = ccall(("list_of_signals", path_to_lib), Int32, 
		(Ref{Cint}, Ref{Cint}, Ptr{Cchar}, Ptr{Cint}),
		ID, NSIG, list, ier)
	return list, nsr[], status, ier[]
end

```

Function returns without an error and the output (after some manipulations) looks something like this:

```julia
permutedims(Char.(list))=
40×24 Matrix{Char}:
 'S' 'I' 'G' 'N' '1' '\0' '\0' '\0' … '\0' '\0' '\0' '\0' '\0' '\0'
 'S' 'I' 'G' 'N' '1' '0' '\0' '\0' '\0' '\0' '\0' '\0' '\0' '\0'
 'S' 'I' 'G' 'N' '1' '1' '\0' '\0' '\0' '\0' '\0' '\0' '\0' '\0'
...etc

```

And I want to _ **convert this Matrix{Char} into Vector{String}** _  
I managed to do it in a relatively ugly way:

```julia
    list_out=Vector{String}(undef,num_of_sigs)
	charlist=Char.(list);
	for i in 1:num_of_sigs
		list_out[i] = String(charlist[:,i]);
	end

```

This successfully converts it to a vector of string, however null termination is not eliminated:

```julia
String[
"SIGN1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"SIGN10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
...

```

And I have an feeling that _ **there should be a more elegant solution** _ (either in the way the input is initially declared and passed to the ccall, or how it is converted/formatted later on)

PS: If there are any suggestions or notes on how the wrapper is written - they are very welcome! I am still a bit confused with Ref{T} and Ptr{T} and was just using Ref=inputs, Ptr=outputs as a rule of thumb, but I am unsure if this is the way to go.

Cheers and thanks for your help!

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [April 8, 2022, 1:59pm UTC](https://discourse.julialang.org/t/formatting-converting-matrix-char-into-vector-string/79224/2 "2022-04-08T13:59:45Z")

</div>

If the orientation of the strings are along the columns of the `charlist`, which it seems you are using, then you can do

```julia
1.7.2> join.(eachcol(charlist))
3-element Vector{String}:
 "SIGN1\0\0\0\0\0\0\0\0\0"
 "SIGN10\0\0\0\0\0\0\0\0"
 "SIGN11\0\0\0\0\0\0\0\0"

```

I’m not sure if there is some better way to chop off the null-characters, but at least you can use `replace`:

```julia
1.7.2> replace.(join.(eachcol(charlist)), '\0'=>"")
3-element Vector{String}:
 "SIGN1"
 "SIGN10"
 "SIGN11"

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [April 8, 2022, 2:14pm UTC](https://discourse.julialang.org/t/formatting-converting-matrix-char-into-vector-string/79224/3 "2022-04-08T14:14:45Z")

</div>

Here’s a version which is quite a bit faster:

```julia
function nulljoin(itr)
    io = IOBuffer()
    for c in itr
        c == '\0' && break
        write(io, c)
    end
    return String(take!(io))
end

```

Then just call

```julia
nulljoin.(eachcol(charlist))

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 8, 2022, 4:30pm UTC](https://discourse.julialang.org/t/formatting-converting-matrix-char-into-vector-string/79224/4 "2022-04-08T16:30:07Z")

</div>

> [@gltchr](#):
>
> `list=Array{Cchar}(undef,24,n_dim);`

Given this, you do _not_ want to convert your 1-byte C `char` values to `Char` (4-byte Unicode values) at all. Not only is this inefficient, but it might be totally wrong if the C library is using UTF-8 encoded Unicode and not just ASCII.

Instead, the most efficient thing (assuming each column of `list` is a NUL-terminated C string) is probably:

```julia
strings = GC.@preserve list unsafe_string.(pointer.(eachcol(list)))

```

(and this is also correct for non-ASCII data if it is UTF-8 encoded).

e.g. using the same data as for your example above:

```julia
julia> list = Int8[83 83 83; 73 73 73; 71 71 71; 78 78 78; 49 49 49; 0 48 49; 0 0 0; 0 0 0; 0 0 0; 0 0 0; 0 0 0; 0 0 0; 0 0 0; 0 0 0; 0 0 0; 0 0 0; 0 0 0; 0 0 0; 0 0 0; 0 0 0; 0 0 0; 0 0 0; 0 0 0; 0 0 0];

julia> strings = GC.@preserve list unsafe_string.(pointer.(eachcol(list)))
3-element Vector{String}:
 "SIGN1"
 "SIGN10"
 "SIGN11"

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [April 9, 2022, 6:45am UTC](https://discourse.julialang.org/t/formatting-converting-matrix-char-into-vector-string/79224/5 "2022-04-09T06:45:05Z")

</div>

> [@gltchr](#):
>
> I have managed to get majority of functions working, but I am unsure about the handling of returned Cchar matrices.  
> Here is an example:
> 
> ```julia
> ##C-call:
> # int list_of_signals(int *, int *, char *, int *)
> # char list[24*N]
> # int ierr, id, ndim, status
> # status = listas_(&id, &ndim, &num_of_sigs, list, &ierr)
> 
> ```

What is the signature of the C-function? It might be possible to have `ccall`/`cconvert` take care of the string conversion, by using `Cstring`.

---

<div class="post-metadata">

**Author:** ![gltchr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gltchr/32/35322_2.png) [@gltchr](https://discourse.julialang.org/u/gltchr)\
**Post date:** [April 11, 2022, 2:49pm UTC](https://discourse.julialang.org/t/formatting-converting-matrix-char-into-vector-string/79224/6 "2022-04-11T14:49:50Z")

</div>

Thank you everyone for providing such a diverse array of answers (I was not expecting for this to happen so fast! Julia community is vigilant 😉 )

---

<div class="post-metadata">

**Author:** ![gltchr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gltchr/32/35322_2.png) [@gltchr](https://discourse.julialang.org/u/gltchr)\
**Post date:** [April 11, 2022, 2:54pm UTC](https://discourse.julialang.org/t/formatting-converting-matrix-char-into-vector-string/79224/7 "2022-04-11T14:54:59Z")

</div>

Signature of the C function is provided in the text that you have cited.  
In particular function takes a **_char[24_N]**\* where N is number of words expected in the output.  
I was playing around with Cstring but it was always returning only the first signal name out of the list (my guess it was exiting on the null-termination character that fills the empty space after the first valid signal name. And because of this I had to turn to the method with a Matrix where each signal name will have it’s own line. From C-code standpoint there is not much difference what “shape” (a string of 24\*N bytes or a matrix of 24columns and N rows) the variable will have as it is passed via the pointer and size matches.

---

<div class="post-metadata">

**Author:** ![gltchr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gltchr/32/35322_2.png) [@gltchr](https://discourse.julialang.org/u/gltchr)\
**Post date:** [April 11, 2022, 2:58pm UTC](https://discourse.julialang.org/t/formatting-converting-matrix-char-into-vector-string/79224/8 "2022-04-11T14:58:49Z")

</div>

This is exactly what I was thinking - there should be a better way and thank you very much for showing it! All the output code is ASCII, so there should not have been a problem, but thanks for highlighting that.

Could I ask to elaborate a bit on the GC.@preserve part? From what I could find it is something related to garbage collection, why it is used in this particular case? Shall it always be used with pointers?

Thanks!

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 11, 2022, 6:20pm UTC](https://discourse.julialang.org/t/formatting-converting-matrix-char-into-vector-string/79224/9 "2022-04-11T18:20:00Z")

</div>

> [@gltchr](#):
>
> Could I ask to elaborate a bit on the GC.@preserve part? From what I could find it is something related to garbage collection, why it is used in this particular case? Shall it always be used with pointers?

Whenever you call `pointer(x)` on an object `x`, you need to make sure that `x` is not garbage-collected before you are done accessing the pointer. For ordinary objects, Julia tracks this automatically, but `pointer(x)` is just an integer address and the compiler loses the connection to `x`. So, you manually call `GC.@preserve x ...calculations with pointer...` to tell Julia to keep `x` around until the calculations are complete.

See also the [`GC.@preserve` documentation](https://docs.julialang.org/en/v1/base/base/#Base.GC.@preserve).
