# Initialize buffer for ccall

**URL:** <https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659>\
**Category:** New to Julia\
**Created:** [December 31, 2020, 1:50pm UTC](https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659 "2020-12-31T13:50:15Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jake](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jake/32/46007_2.png) [@Jake](https://discourse.julialang.org/u/Jake)\
**Post date:** [December 31, 2020, 1:50pm UTC](https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659/1 "2020-12-31T13:50:15Z")

</div>

I am using the Raspberry PI running Raspbian and Julia to interface with the MCC 172 DSP board. The MCC 172 has a complete c library. I am working on making those calls accessible to Julia using the ccall functionality.

I find that I learn best through examples, and have not yet found an example for initialising a buffer in Julia to pass to the c-program through ccall and have the c-program fill the buffer and return it to Julia. The documentation for the c-function is at  
[C Library Reference — MCC DAQ HAT Library 1.4.0 documentation](https://mccdaq.github.io/daqhats/c.html#analog-input-scan-option-flags) near the bottom.

My code snippet is:

```julia
# Reads status and multiple samples from an analog input scan.	
# documentation https://mccdaq.github.io/daqhats/c.html#analog-input-scan-option-flags
function mcc172_a_in_scan_read(address::Integer, samples_per_channel::UInt32, mcc172_num_channels::Integer, timeout::Float64)
	
	status = Ref{UInt16}(0) # Initialize
	buffer_size_samples = samples_per_channel * UInt32(mcc172_num_channels)	# Initialize
	buffer = Ref{Array{Float64,1}} #(0.0,buffer_size)
	samples_read_per_channel = Ref{UInt32}(0) # Initialize
	@show(status[], buffer_size_samples[], samples_read_per_channel[], buffer)
	
	success = ccall((:mcc172_a_in_scan_read, "/usr/local/lib/libdaqhats.so"),
	Cint, (UInt8, Ref{UInt16}, UInt32, Cdouble, Ref{Array{Float64,1}}, UInt32, Ref{UInt32}), 
	UInt8(address), status, samples_per_channel, timeout, buffer, buffer_size_samples, samples_read_per_channel)
	@show(status[], buffer_size_samples[], samples_read_per_channel[])
	return "Fini"
end

```

The combination printout and error message I get follows, where line 306 actually is the line success = ccall(…

```julia
julia> mcc172_a_in_scan_read(UInt8(0),UInt32(1024), 4, 4.0)
status[] = 0x0000
buffer_size_samples[] = 0x00001000
samples_read_per_channel[] = 0x00000000
buffer = Ref{Array{Float64,1}}
ERROR: MethodError: Cannot `convert` an object of type Type{Ref{Array{Float64,1}}} to an object of type Array{Float64,1}
Closest candidates are:
  convert(::Type{T}, ::AbstractArray) where T<:Array at array.jl:554
  convert(::Type{T}, ::T) where T<:AbstractArray at abstractarray.jl:14
  convert(::Type{T}, ::LinearAlgebra.Factorization) where T<:AbstractArray at /home/pi/work/build/usr/share/julia/stdlib/v1.5/LinearAlgebra/src/factorization.jl:55
  ...
Stacktrace:
 [1] Base.RefValue{Array{Float64,1}}(::Type{T} where T) at ./refvalue.jl:8
 [2] convert(::Type{Ref{Array{Float64,1}}}, ::Type{T} where T) at ./refpointer.jl:63
 [3] cconvert(::Type{T} where T, ::Type{T} where T) at ./essentials.jl:388
 [4] mcc172_a_in_scan_read(::UInt8, ::UInt32, ::Int32, ::Float64) at /home/pi/daqhatsJulia/daqhats.jl:306
 [5] top-level scope at REPL[160]:1

```

I think I need to initialize buffer differently or modify the type tuple for the buffer type in the ccall function.

Help is appreciated.

---

<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 31, 2020, 2:23pm UTC](https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659/2 "2020-12-31T14:23:29Z")

</div>

`buffer = Ref{Array{Float64,1}}` is certainly wrong. This a type, not even an instance of a `Ref` type — that is, `buffer isa Type` returns `true`. From the documentation, `buffer` should be an _allocated_ array, i.e. `buffer` should be an `Array{Float64,1}` (a `Vector{Float64}`) of length `buffer_size_samples`.

Also, when you pass the `buffer` to the `ccall` it should be as a `Ptr{Cdouble}`. Julia knows how to pass an `Array` to a pointer argument. Note also that `ccall` will automatically convert arguments by calling `convert` — there’s no need to explicitly convert to `UInt8` etcetera.

That is, it should probably look something like this:

```julia
function mcc172_a_in_scan_read(address::Integer, samples_per_channel::Integer, mcc172_num_channels::Integer, timeout::Real)
	status = Ref{UInt16}()
	buffer_size_samples = samples_per_channel * mcc172_num_channels
	buffer = Vector{Float64}(undef, buffer_size_samples)
	samples_read_per_channel = Ref{UInt32}()
	
	success = ccall((:mcc172_a_in_scan_read, "/usr/local/lib/libdaqhats.so"),
	    Cint, (UInt8, Ref{UInt16}, UInt32, Cdouble, Ptr{Cdouble}, UInt32, Ref{UInt32}), 
	    address, status, samples_per_channel, timeout, buffer, buffer_size_samples, samples_read_per_channel)
    return buffer, Int(samples_read_per_channel[]), status[]
end

```

or maybe `resize!(buffer, samples_read_per_channel[] * mcc172_num_channels)`. Note that you don’t need to initialize the `Ref` arguments with a value since (if I understand the documentation for `mcc172_a_in_scan_read` correctly) they are purely output parameters.

---

<div class="post-metadata">

**Author:** ![Jake](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jake/32/46007_2.png) [@Jake](https://discourse.julialang.org/u/Jake)\
**Post date:** [December 31, 2020, 4:07pm UTC](https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659/3 "2020-12-31T16:07:03Z")

</div>

Thank-you very much, that is very helpful. It works now.

Happy New Year to you and all who faithfully provide answers to those like me.

---

<div class="post-metadata">

**Author:** ![Jake](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jake/32/46007_2.png) [@Jake](https://discourse.julialang.org/u/Jake)\
**Post date:** [January 1, 2021, 9:38pm UTC](https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659/4 "2021-01-01T21:38:05Z")

</div>

Now I am trying to initialize a structure for ccall using the same library as previously and having problems.

I am not sure if my struct is initialized correctly, or if there is a problem with the parameters in ccall.  
The c-function I am calling is:

int `hat_list` (uint16\_t _filter\_id_ , struct [HatInfo](https://mccdaq.github.io/daqhats/c.html#c.HatInfo) \* _list_ )

```julia
# Global functions and data - https://mccdaq.github.io/daqhats/c.html
# description of function https://mccdaq.github.io/daqhats/c.html#daqhats_8h_1a30cd29e26738a6f6d11746f3ccfa06e8

mutable struct HatInfo
    address::UInt8 # The board address.
    id::UInt16 # The product ID, one of [HatIDs](@ref HatIDs)
    version::UInt16 # The hardware version
    product_name::String	# The product name (c - initialized to 256 characters)
end

"""
	hat_list(filter_id)
Return a list of detected DAQ HAT boards.
"""
function hat_list(filter_id::String)
	idDict = Dict{String, UInt32}(
	"HAT_ID_ANY" => 0, # Match any DAQ HAT ID in hat_list().
	"HAT_ID_MCC_118" => 0x0142, # MCC 118 ID.
	"HAT_ID_MCC_118_BOOTLOADER" => 0x8142, # MCC 118 in firmware update mode ID.
	"HAT_ID_MCC_128" => 0x0146, # MCC 128 ID.
	"HAT_ID_MCC_134" => 0x0143, # MCC 134 ID.
	"HAT_ID_MCC_152" => 0x0144, # MCC 152 ID.
	"HAT_ID_MCC_172" => 0x0145) # MCC 172 ID.
	
	list = HatInfo(0, 0, 0, repeat('a', 256))
#	@show(list)
	success = ccall((:hat_list, "/usr/local/lib/libdaqhats"), 
	Cint, (UInt16, Ptr{HatInfo}), idDict[filter_id], list)
#	@show(list)
	#list = unsafe_load(Ptr{HatInfo}(list))
end

```

the output from this is

```julia
julia> hat_list("HAT_ID_ANY")
ERROR: MethodError: no method matching unsafe_convert(::Type{Ptr{HatInfo}}, ::HatInfo)
Closest candidates are:
  unsafe_convert(::Type{T}, ::T) where T<:Ptr at essentials.jl:391
  unsafe_convert(::Type{Ptr{T}}, ::Ptr{Tuple{Vararg{T,N}}}) where {N, T} at refpointer.jl:136
  unsafe_convert(::Type{P}, ::Ptr) where P<:Ptr at essentials.jl:392
  ...
Stacktrace:
 [1] hat_list(::String) at /home/pi/daqhatsJulia/daqhats172.jl:44
 [2] top-level scope at REPL[3]:1

```

where line 44 is the ccall function.

reading the c-function description some more I find I will need to create an array of structures to pass into the function, which is even more daunting.

---

<div class="post-metadata">

**Author:** ![Jake](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jake/32/46007_2.png) [@Jake](https://discourse.julialang.org/u/Jake)\
**Post date:** [January 2, 2021, 4:03am UTC](https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659/5 "2021-01-02T04:03:21Z")

</div>

I did some more experimenting with trying to duplicate the following section of code from the documentation that involves the NULL pointer. The documentation tells me that: There is no invalid (NULL) `Ref` in Julia, but a `C_NULL` instance of `Ptr` can be passed to a `ccall` Ref argument.

```julia
int count = hat_list(HAT_ID_ANY, NULL);

if (count > 0)
{
    struct HatInfo* list = (struct HatInfo*)malloc(count * 
        sizeof(struct HatInfo));
    hat_list(HAT_ID_ANY, list);

    // perform actions with list

    free(list);
}

```

to call the first line of code I tried where the idDict is given in the previous post.

```julia
count = ccall((:hat_list, "/usr/local/lib/libdaqhats"), 
	Cint, (UInt16, Ref{C_NULL}), idDict["HAT_ID_ANY"], 0)

```

This gives the following error message

```julia
julia> hat_list("HAT_ID_ANY")
ERROR: MethodError: First argument to `convert` must be a Type, got Ptr{Nothing} @0x00000000
Stacktrace:
 [1] Base.RefValue{Ptr{Nothing} @0x00000000}(::Int32) at ./refvalue.jl:8
 [2] convert(::Type{Ref{Ptr{Nothing} @0x00000000}}, ::Int32) at ./refpointer.jl:63
 [3] cconvert(::Type{T} where T, ::Int32) at ./essentials.jl:388
 [4] hat_list(::String) at /home/pi/daqhatsJulia/daqhats172.jl:42
 [5] top-level scope at REPL[7]:1

```

I appreciate all 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:** [January 2, 2021, 2:28pm UTC](https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659/6 "2021-01-02T14:28:32Z")

</div>

> [@Jake](#):
>
> int `hat_list` (uint16\_t _filter\_id_ , struct [HatInfo](https://mccdaq.github.io/daqhats/c.html#c.HatInfo) \* _list_ )

If `list` is a _single_ `HatInfo` struct, then you should declare the `ccall` parameter as `Ref{HatInfo}` and pass a `hatinfo = Ref{HatInfo}()` object. Then get the value with `hatinfo[]`.

If `list` is an _array_ of `HatInfo` structs, then you should declare the parameter as `Ptr{HatInfo}` and pass an array. (But it doesn’t look like this is the case since you don’t pass an array length?)

---

<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:** [January 2, 2021, 2:31pm UTC](https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659/7 "2021-01-02T14:31:08Z")

</div>

> [@Jake](#):
>
> ```julia
> ccall((:hat_list, "/usr/local/lib/libdaqhats"), 
> Cint, (UInt16, Ref{C_NULL}), idDict["HAT_ID_ANY"], 0)
> 
> ```

`C_NULL` is an instance (a pointer _value_) of `Ptr{Cvoid}`, not a pointer type. If you want to pass a `NULL` argument you should do:

```julia
count = ccall((:hat_list, "/usr/local/lib/libdaqhats"), 
   	Cint, (UInt16, Ptr{Cvoid}), idDict["HAT_ID_ANY"], C_NULL)

```

(Then to allocate `list` you would then do `list = Vector{HatInfo}(undef, count)`, and pass it as a `Ptr{HatInfo}` argument to the subsequent `hat_list` call.)

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [January 2, 2021, 3:51pm UTC](https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659/8 "2021-01-02T15:51:22Z")

</div>

> [@Jake](#):
>
> ```julia
> mutable struct HatInfo
> address::UInt8 # The board address.
> id::UInt16 # The product ID, one of [HatIDs](@ref HatIDs)
> version::UInt16 # The hardware version
> product_name::String	# The product name (c - initialized to 256 characters)
> end
> 
> ```
> 
> …  
> list = HatInfo(0, 0, 0, repeat(‘a’, 256))

I think you will have troubles here (Julia crash). At least I always have when I try it. The problem seems to be that the `product_name::String` does not allocate the 256 chars needed in the C side.  
Following what LLVM.jl does, declare it as `product_name::NTuple{256,UInt8}` and

```julia
list = HatInfo(0, 0, 0, map(UInt8, (string(repeat(" ",256))...,)))

```

then you would recover the text with

```julia
String([list.product_name...])

```

Very painful.

---

<div class="post-metadata">

**Author:** ![Jake](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jake/32/46007_2.png) [@Jake](https://discourse.julialang.org/u/Jake)\
**Post date:** [January 2, 2021, 5:39pm UTC](https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659/9 "2021-01-02T17:39:02Z")

</div>

I am making progress slowly. Thanks Steve I have ccall finding the count working. I believe C generates the total memory required by using the count function as follows:

```julia
   info_list = (struct HatInfo*)malloc(info_count * sizeof(struct HatInfo));

```

This means the number of items in the array can be calculated ahead of time.

Thanks to joa-quim I have updated my struct and am generating a data structure in Julia that should match the size generated in C. My code now works, except for when I uncomment (shown uncommented below) the second ccall function, it won’t compile then with the following message:

```julia
could not evaluate ccall argument type (it might depend on a local variable)

```

Code shown below:

```julia
# Global functions and data - https://mccdaq.github.io/daqhats/c.html

mutable struct HatInfo
    address::UInt8 # The board address.
    id::UInt16 # The product ID, one of [HatIDs](@ref HatIDs)
    version::UInt16 # The hardware version
    product_name::NTuple{256,UInt8}	# The product name (c - initialized to 256 characters)
end

"""
	hat_list(filter_id)
Return a list of detected DAQ HAT boards.
"""
function hat_list(filter_id::String)
	idDict = Dict{String, UInt32}(
	"HAT_ID_ANY" => 0, # Match any DAQ HAT ID in hat_list().
	"HAT_ID_MCC_118" => 0x0142, # MCC 118 ID.
	"HAT_ID_MCC_118_BOOTLOADER" => 0x8142, # MCC 118 in firmware update mode ID.
	"HAT_ID_MCC_128" => 0x0146, # MCC 128 ID.
	"HAT_ID_MCC_134" => 0x0143, # MCC 134 ID.
	"HAT_ID_MCC_152" => 0x0144, # MCC 152 ID.
	"HAT_ID_MCC_172" => 0x0145) # MCC 172 ID.
	
	count = ccall((:hat_list, "/usr/local/lib/libdaqhats"), 
	Cint, (UInt16, Ptr{Cvoid}), idDict["HAT_ID_ANY"], C_NULL)
	@show(count)
	list = Vector{HatInfo}(undef,count)
	@show(list)
	for i = 1:count
		list[i] = HatInfo(0, 0, 0, map(UInt8, (string(repeat(" ",256))...,)))
	end
	
	success = ccall((:hat_list, "/usr/local/lib/libdaqhats"), 
	Cint, (UInt16, Ptr{list}), idDict[filter_id], list)
#	String([list.product_name...])
#	list = unsafe_load(Ptr{HatInfo}(list))
end

```

I suspect that my Ptr{list} should be a Ref{list} and that somehow I need to get the pointer to list rather than the variable list, but am not sure how to do that with my data structure. Thanks in advance.

---

<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:** [January 2, 2021, 6:33pm UTC](https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659/10 "2021-01-02T18:33:46Z")

</div>

> [@Jake](#):
>
> `mutable struct`

Shouldn’t be mutable. You need it to be immutable so that the Vector will store the data inline rather than as an array of pointers.

---

<div class="post-metadata">

**Author:** ![Jake](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jake/32/46007_2.png) [@Jake](https://discourse.julialang.org/u/Jake)\
**Post date:** [January 2, 2021, 7:19pm UTC](https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659/11 "2021-01-02T19:19:01Z")

</div>

I made that change.

Now when I try to compile by restarting Julia and using the includet command, I get the following error:

```julia
could not evaluate ccall argument type (it might depend on a local variable)

```

I tried changing the Ptr{list} to Ref{list} but received the same error.

---

<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:** [January 2, 2021, 8:00pm UTC](https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659/12 "2021-01-02T20:00:03Z")

</div>

> [@Jake](#):
>
> `could not evaluate ccall argument type (it might depend on a local variable)`

That’s because you declared the argument type as `Ptr{list}` rather than `Ptr{HatInfo}`. Argument types should be _types_.

---

<div class="post-metadata">

**Author:** ![Jake](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jake/32/46007_2.png) [@Jake](https://discourse.julialang.org/u/Jake)\
**Post date:** [January 5, 2021, 12:47am UTC](https://discourse.julialang.org/t/initialize-buffer-for-ccall/52659/13 "2021-01-05T00:47:24Z")

</div>

Thanks for your help. All is working now. I have put the code below for those following along and curious of how the working code works. Note that I used a for loop for a reverse lookup from the Dictionary. A table may work better but for the small number of values this works.

As a Julia beginner coming from Matlab it took me a while to figure out that a variable introduced within a for loop is not visible outside the for loop. It would be good to add this in Chapter 41, noteworthy differences from Matlab.

```julia
# Global functions and data - https://mccdaq.github.io/daqhats/c.html

struct HatInfoTemp
    address::UInt8 # The board address.
    id::UInt16 # The product ID, one of [HatIDs](@ref HatIDs)
    version::UInt16 # The hardware version
    product_name::NTuple{256,UInt8}	# The product name (c - initialized to 256 characters)
end

struct HatInfo
    address::UInt8 # The board address.
    id::String # The product ID, one of [HatIDs](@ref HatIDs)
    version::UInt16 # The hardware version
    product_name::String	# The product name
end

"""
	hat_list(filter_id)
Return a list of detected DAQ HAT boards.
"""
function hat_list(filter_id::String)
	idDict = Dict{String, UInt16}(
	"HAT_ID_ANY" => 0, # Match any DAQ HAT ID in hat_list().
	"HAT_ID_MCC_118" => 0x0142, # MCC 118 ID.
	"HAT_ID_MCC_118_BOOTLOADER" => 0x8142, # MCC 118 in firmware update mode ID.
	"HAT_ID_MCC_128" => 0x0146, # MCC 128 ID.
	"HAT_ID_MCC_134" => 0x0143, # MCC 134 ID.
	"HAT_ID_MCC_152" => 0x0144, # MCC 152 ID.
	"HAT_ID_MCC_172" => 0x0145) # MCC 172 ID.
	
	count = ccall((:hat_list, "/usr/local/lib/libdaqhats"), 
	Cint, (UInt16, Ptr{Cvoid}), idDict[filter_id], C_NULL)
	listTemp = Vector{HatInfoTemp}(undef,count)
	list = Vector{HatInfo}(undef,count)
	for i = 1:count
		listTemp[i] = HatInfoTemp(0, 0, 0, map(UInt8, (string(repeat(" ",256))...,)))
	end
	
	success = ccall((:hat_list, "/usr/local/lib/libdaqhats"), 
	Cint, (UInt16, Ptr{HatInfoTemp}), idDict[filter_id], listTemp)
	for i = 1:count
		a = String([listTemp[i].product_name...])
		f = findfirst(Char(0x0), a)
		p = SubString(a, 1:f-1)
		keyvalue = othervalue = ""
		for k in keys(idDict) # reverse lookup in Dictionary idDict
			if idDict[k] == listTemp[i].id
				keyvalue = k
				break
			end
			
		end
		list[i] = HatInfo(listTemp[i].address, keyvalue, listTemp[i].version, p)
	end
	return list	
end

```
