# Ccall printf works with ints but not with floats. Why?

**URL:** <https://discourse.julialang.org/t/ccall-printf-works-with-ints-but-not-with-floats-why/52487>\
**Category:** General Usage\
**Created:** [December 28, 2020, 1:38am UTC](https://discourse.julialang.org/t/ccall-printf-works-with-ints-but-not-with-floats-why/52487 "2020-12-28T01:38:01Z")\
**Posts on this page:** 8\
**Page:** 1

<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:** [December 28, 2020, 1:38am UTC](https://discourse.julialang.org/t/ccall-printf-works-with-ints-but-not-with-floats-why/52487/1 "2020-12-28T01:38:01Z")

</div>

```julia
julia> ccall(:printf, Cint, (Ptr{Cchar}, Cint), "aiai %d", 10);
aiai 10
julia> ccall(:printf, Cint, (Ptr{Cchar}, Cdouble), "aiai %f", 10.99);
aiai 0.000000

```

The context for this is to reduce _invalidations_ that cause latency.

```julia
using SnoopCompile
precompile(plot, (Array{Float64,2},));

tinf = @snoopi tmin=0.01 plot([0.0 0; 1.1 1])
5-element Vector{Tuple{Float64, Core.MethodInstance}}:
 (0.015999794006347656, MethodInstance for GMT.check_caller(::Dict{Symbol, Any}, ::String, ::String, ::String, ::String, ::Nothing, ::Bool))
 (0.03399991989135742, MethodInstance for hvcat(::Tuple{Int64, Int64}, ::Float64, ::Vararg{Number, N} where N))
 (0.0409998893737793, MethodInstance for Printf.format(::Vector{UInt8}, ::Int64, ::Printf.Format{Base.CodeUnits{UInt8, String}, NTuple{4, Printf.Spec{Val{'g'}}}}, ::Float64, ::Vararg{Float64, N} where N))
 (0.07500004768371582, MethodInstance for GMT.add_opt(::Dict{Symbol, Any}, ::String, ::Char, ::Matrix{Symbol}, ::Symbol, ::Vector{Union{Nothing, Matrix{Float64}}}, ::NamedTuple{(:outline, :fill), Tuple{String, String}}))
 (0.24000000953674316, MethodInstance for Printf.format(::Printf.Format{Base.CodeUnits{UInt8, String}, NTuple{4, Printf.Spec{Val{'g'}}}}, ::Float64, ::Float64, ::Float64, ::Vararg{Float64, N} where N))

```

So _Printf_ is responsible for some non-negligible invalidation. The above happens in a line with

```julia
opt_R = @sprintf(" -R%.12g/%.12g/%.12g/%.12g", info[1].data[1], info[1].data[2],
							 info[1].data[3], info[1].data[4])

```

I checked that because if I replace the above with a `opt_R = " -R1/2/3/4"` the recompilation goes away. So my idea was to try to access the `libc` `sprintf` directly but I can’t make it work for floats. only for ints.

---

<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:** [December 28, 2020, 3:20pm UTC](https://discourse.julialang.org/t/ccall-printf-works-with-ints-but-not-with-floats-why/52487/2 "2020-12-28T15:20:21Z")

</div>

Hmm, this seems to be a Windows issue. If I use `@ccall` it doesn’t work either

```julia
julia> str = " ";

julia> @ccall sprintf(str::Cstring, "%s = %d"::Cstring ; "foo"::Cstring, 6::Cint)::Cint;

julia> str
"foo = 6\0 "

julia> str = " ";

julia> @ccall sprintf(str::Cstring, "%s = %f"::Cstring ; "foo"::Cstring, 6.6666::Cdouble)::Cint;

julia> str
"foo = f\0 "

```

but in WSL

```julia
julia> str = " ";

julia> @ccall sprintf(str::Cstring, "%s = %f"::Cstring ; "foo"::Cstring, 6.6666::Cdouble)::Cint;

julia> str
"foo = 6.666600\0 "

```

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [December 28, 2020, 4:50pm UTC](https://discourse.julialang.org/t/ccall-printf-works-with-ints-but-not-with-floats-why/52487/3 "2020-12-28T16:50:12Z")

</div>

`printf` is vararg, calling vararg functions is tricky.

---

<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:** [December 28, 2020, 5:02pm UTC](https://discourse.julialang.org/t/ccall-printf-works-with-ints-but-not-with-floats-why/52487/4 "2020-12-28T17:02:01Z")

</div>

That is why I tried the @ccall macro that supports vararg

---

<div class="post-metadata">

**Author:** ![Paul\_Soderlind](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paul_soderlind/32/1753_2.png) [@Paul\_Soderlind](https://discourse.julialang.org/u/Paul_Soderlind)\
**Post date:** [December 28, 2020, 8:04pm UTC](https://discourse.julialang.org/t/ccall-printf-works-with-ints-but-not-with-floats-why/52487/5 "2020-12-28T20:04:55Z")

</div>

I am not really sure about printf, but for sprintf I do the following on Windows 10 (Julia 1.5):

```julia
strp = Ref{Ptr{Cchar}}(0)
len = ccall(:asprintf,Cint,(Ptr{Ptr{Cchar}},Cstring,Cdouble...),strp,fmt,z)
str = unsafe_string(strp[],len)
Libc.free(strp[])

```

where `fmt` is a traditional formatting string, `z` is the number I want to print and `str` is the output.

Maybe of some help.

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [December 28, 2020, 8:09pm UTC](https://discourse.julialang.org/t/ccall-printf-works-with-ints-but-not-with-floats-why/52487/6 "2020-12-28T20:09:57Z")

</div>

Those aren’t invalidations, they are triggers of type-inference. `@snoopr` is what measures invalidations.  
[https://timholy.github.io/SnoopCompile.jl/stable/snoopr/](https://timholy.github.io/SnoopCompile.jl/stable/snoopr/)

You can eliminate most of that time by adding precompiles in your package for whatever function has that `@sprintf`, but those will work only if the call to `Printf.format` is inferrable. Check `@code_typed` and see whether it’s an `invoke` (inferrable) or a `call` (non-inferrable).

---

<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:** [December 29, 2020, 12:34am UTC](https://discourse.julialang.org/t/ccall-printf-works-with-ints-but-not-with-floats-why/52487/7 "2020-12-29T00:34:57Z")

</div>

> [@tim.holy](#):
>
> You can eliminate most of that time by adding precompiles in your package for whatever function has that `@sprintf` ,

Thanks, but I don’t know how to do that. Those `@sprintf` live in a common function that is called by the GMT `plot` module as well as several other modules. That function does a first round reading the input data, finds the BoundingBox and creates a (string) option with that info. The precompile

```julia
precompile(plot, (Array{Float64,2},));

```

should exercise that function, and in fact it seems to do it in Julia 1.5 where this latency (or how should I call it) does not exist. But it does on Julia 1.6 where the whole GMT package gets slower (to start).

```julia
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 1.7.0-DEV.54 (2020-12-13)
 _/ |\ __'_|_|_|\__'_| | Commit 6ddc7f1ecc (15 days old master)
|__/ |

julia> @time using GMT
[Info: Precompiling GMT [5752ebe1-31b9-557e-87aa-f909b540aa54]
 18.023743 seconds (2.24 M allocations: 137.498 MiB, 0.22% gc time, 5.17% compilation time)

julia> @time plot([0.0 0; 1.1 1])
  4.668330 seconds (3.76 M allocations: 176.236 MiB, 2.92% gc time, 99.39% compilation time)

```

and in 1.5

```julia
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 1.5.3 (2020-11-09)
 _/ |\ __'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |

julia> @time using GMT
[Info: Precompiling GMT [5752ebe1-31b9-557e-87aa-f909b540aa54]
 17.095942 seconds (1.77 M allocations: 99.291 MiB, 0.23% gc time)

julia> @time plot([0.0 0; 1.1 1])
  3.799247 seconds (1.04 M allocations: 54.201 MiB, 0.30% gc time)

```

---

<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:** [December 29, 2020, 12:37am UTC](https://discourse.julialang.org/t/ccall-printf-works-with-ints-but-not-with-floats-why/52487/8 "2020-12-29T00:37:05Z")

</div>

Thanks, I’ll certainly explore it if the _apparent_ 1.6 regression in @sprintf steps in the way.
