# Julia equivalent of C argument \`char \*\*attrlist\[\]\`

**URL:** <https://discourse.julialang.org/t/julia-equivalent-of-c-argument-char-attrlist/92169>\
**Category:** New to Julia\
**Tags:** strings, array, c, char\
**Created:** [December 26, 2022, 9:27pm UTC](https://discourse.julialang.org/t/julia-equivalent-of-c-argument-char-attrlist/92169 "2022-12-26T21:27:58Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)\
**Post date:** [December 26, 2022, 9:27pm UTC](https://discourse.julialang.org/t/julia-equivalent-of-c-argument-char-attrlist/92169/1 "2022-12-26T21:27:58Z")

</div>

Hi! I am trying to access from Julia a C function whose header is declared as follows:

```julia
MTKt_status MtkFileAttrList( const char *filename,
    int *attrcnt,
    char **attrlist[] );

```

where the output argument `attrlist` should be a list of 31 (string) file attributes, such as

```julia
HDFEOSVersion
StructMetadata.0
Path_number
AGP_version_id
DID_version_id
Number_blocks
...
Cam_mode
Num_local_modes
Local_mode_site_name
Orbit_QA
Camera
coremetadata

```

I’ve tentatively written the Julia wrapper as

```julia
function MtkFileAttrList(filename, attrcnt, attrlist)
    status = ccall((:MtkFileAttrList, mtklib),
        Cint,
        (Cstring, Ptr{Cint}, Vector{Ptr{Ptr{UInt8}}}),
        filename, attrcnt, attrlist)
    return status
end

```

When I call this wrapper function,

```julia
julia> filename = "./data/MISR/MISR_AM1_GRP_TERRAIN_GM_P168_O068050_BA_F03_0024.hdf"
"./data/MISR/MISR_AM1_GRP_TERRAIN_GM_P168_O068050_BA_F03_0024.hdf"

julia> attrcnt = Ref{Int32}(0)
Base.RefValue{Int32}(0)

julia> attrlist = Vector{Ref{Ptr{UInt8}}}()
Ref{Ptr{UInt8}}[]

julia> status = MtkFileAttrList(filename, attrcnt, attrlist)
0

julia> typeof(attrlist)
Vector{Ref{Ptr{UInt8}}} (alias for Array{Ref{Ptr{UInt8}}, 1})

julia> typeof(attrlist[])
ERROR: BoundsError: attempt to access 0-element Vector{Ref{Ptr{UInt8}}} at index []
Stacktrace:
 [1] throw_boundserror(A::Vector{Ref{Ptr{UInt8}}}, I::Tuple{})
   @ Base ./abstractarray.jl:703
 [2] checkbounds
   @ ./abstractarray.jl:668 [inlined]
 [3] _getindex
   @ ./abstractarray.jl:1273 [inlined]
 [4] getindex(::Vector{Ref{Ptr{UInt8}}})
   @ Base ./abstractarray.jl:1241
 [5] top-level scope
   @ REPL[13]:1

```

so the function does not detect any error (status is 0) and returns the correct number of attributes (31), but the output argument `attrlist` appears to be empty: I suspect its definition or usage is incorrect. I thus have 3 questions:

1. Is the initial declaration of the `attrlist = Vector{Ref{Ptr{UInt8}}}()` correctly setup?

2. Is the `ccall` argument `Vector{Ptr{Ptr{UInt8}}}` correctly specified?

3. How do I access the individual items in the output list `attrlist`, once it will actually contain the expected attribute list?

Thanks for suggestions on these questions.

---

<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:** [December 26, 2022, 9:55pm UTC](https://discourse.julialang.org/t/julia-equivalent-of-c-argument-char-attrlist/92169/2 "2022-12-26T21:55:08Z")

</div>

> [@mmv](#):
>
> `(Cstring, Ptr{Cint}, Vector{Ptr{Ptr{UInt8}}}),`

This doesn’t seem right. First, it is cleaner to make the second argument `Ref{Cint}`. Second, the third argument should be `Ref{Ptr{Ptr{UInt8}}}`, and you should definitely _not_ pass in a `Vector` (a _Julia_-allocated) array. The reason is that the `attrlist` is allocated by the _C_ function, _not_ by Julia — it is [documented as](https://nasa.github.io/MISR-Toolkit/html/_mtk_file_attr_list_8c.html) an _output_ parameter.

Instead, you probably want something like:

```julia
# to do: more descriptive errors
function mtk_checkstatus(status::Integer)
    status != 0 && error("MTK error $status")
end

function MtkFileAttrList(filename::AbstractString)
    num_attrs = Ref{Cint}()
    attrlist = Ref{Ptr{Ptr{UInt8}}()
    status = @ccall mtklib.MtkFileAttrList(filename::Cstring, num_attrs::Ref{Cint}, attrlist::Ref{Ptr{Ptr{UInt8}})::Cint
    mtk_checkstatus(status)
    julia_attrlist = [unsafe_string(unsafe_load(attrlist[], i)) for i in 1:num_attrs[]]
    status = @ccall mtklib.MtkStringListFree(num_attrs[]::Cint, attrlist::Ref{Ptr{Ptr{UInt8}}})::Cint
    mtk_checkstatus(status)
    return julia_attrlist
end

```

which calls `MtkFileAttrList` to get the attribute list, then converts it into a native Julia array of strings, then frees the `char **` with [`MtkStringListFree`](https://nasa.github.io/MISR-Toolkit/html/_misr_util_8h.html#add3fb7e1d11102fe685dda68d36a421a), and finally returns the native Julia array.

ccall((:MtkFileAttrList, mtklib), Cint, (C

```julia

```

---

<div class="post-metadata">

**Author:** ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)\
**Post date:** [December 26, 2022, 10:31pm UTC](https://discourse.julialang.org/t/julia-equivalent-of-c-argument-char-attrlist/92169/3 "2022-12-26T22:31:05Z")

</div>

Thanks a lot, @stevengj! That works (of course…)

I have these follow-up questions, though:

- Is there an advantage in using `@ccall` rather than `ccall`, or is it just a matter of style or personal preference?

- In all examples I had seen previously, function arguments were declared wit `Ref` outside the `ccall` and `Ptr` inside that call. Are those equivalent and interchangeable?

Thanks again for your input.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [December 26, 2022, 10:34pm UTC](https://discourse.julialang.org/t/julia-equivalent-of-c-argument-char-attrlist/92169/4 "2022-12-26T22:34:06Z")

</div>

The main advantages of `@ccall` are that it removes some of the possible ways to mess it up and is a bit cleaner.

---

<div class="post-metadata">

**Author:** ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)\
**Post date:** [December 26, 2022, 10:52pm UTC](https://discourse.julialang.org/t/julia-equivalent-of-c-argument-char-attrlist/92169/5 "2022-12-26T22:52:06Z")

</div>

Hi @Oscar_Smith: Thanks for answering this question. Could you expand a bit on your reasoning? As a novice, it appears to me that the following statements

```julia
status = ccall((:MtkFileAttrList, mtklib),
    Cint,
    (Cstring, Ref{Cint}, Ref{Ptr{Ptr{UInt8}}}),
    filename, attrcnt, attrlist)

```

and

```julia
status =@ccall mtklib.MtkFileAttrList(
    filename::Cstring,
    num_attrs::Ref{Cint},
    attrlist::Ref{Ptr{Ptr{UInt8}}})::Cint

```

are equivalent and just organized in a different way: in what sense does the second form “remove some of the possible ways to mess it up”? Thanks for your help!

---

<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:** [December 26, 2022, 11:31pm UTC](https://discourse.julialang.org/t/julia-equivalent-of-c-argument-char-attrlist/92169/6 "2022-12-26T23:31:54Z")

</div>

> [@mmv](#):
>
> are equivalent and just organized in a different way

`@ccall` is indeed equivalent to `ccall`. But because `@ccall` puts the argument types next to the arguments, instead of in two separate lists, it seems a bit less prone to accidental mismatches.

---

<div class="post-metadata">

**Author:** ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)\
**Post date:** [December 26, 2022, 11:35pm UTC](https://discourse.julialang.org/t/julia-equivalent-of-c-argument-char-attrlist/92169/7 "2022-12-26T23:35:21Z")

</div>

Thanks @stevengj: Point well taken…

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [December 27, 2022, 12:32pm UTC](https://discourse.julialang.org/t/julia-equivalent-of-c-argument-char-attrlist/92169/8 "2022-12-27T12:32:09Z")

</div>

> [@mmv](#):
>
> Is there an advantage in using `@ccall` rather than `ccall`, or is it just a matter of style or personal preference?

in general, you have to

1. use `@ccall` for calling a C variadic function with variadic argument types,
2. use `ccall` if you need to specify a calling convention.

---

<div class="post-metadata">

**Author:** ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)\
**Post date:** [December 28, 2022, 10:23pm UTC](https://discourse.julialang.org/t/julia-equivalent-of-c-argument-char-attrlist/92169/9 "2022-12-28T22:23:33Z")

</div>

Hi @Gnimuc,

Thanks for this additional point: Most if not all Mtk functions expect a fixed number of arguments, though some of them can be empty strings, for instance.
