# Ccall works on global scope but not within function

**URL:** <https://discourse.julialang.org/t/ccall-works-on-global-scope-but-not-within-function/72119>\
**Category:** General Usage\
**Tags:** ccall, c\
**Created:** [November 26, 2021, 2:55pm UTC](https://discourse.julialang.org/t/ccall-works-on-global-scope-but-not-within-function/72119 "2021-11-26T14:55:23Z")\
**Posts on this page:** 1\
**Showing post:** 4

<div class="post-metadata">

**Author:** ![xor0110](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xor0110/32/7926_2.png) [@xor0110](https://discourse.julialang.org/u/xor0110)\
**Post date:** [November 27, 2021, 12:25pm UTC](https://discourse.julialang.org/t/ccall-works-on-global-scope-but-not-within-function/72119/4 "2021-11-27T12:25:29Z")

</div>

Thanks, I did make the mistake with `pointer` before, but I fixed that after I started using Clang.jl to generate the bindings.

Here’s a slightly involved example that supposedly reproduces how this library works. I’m not sure I reproduced all the bugs, but it does illustrate one of the issues I’m having. I’m using [this way](https://discourse.julialang.org/t/interpret-ntuple-1024-uint8-as-a-c-string/23906) to transform `NTuple{N, UInt8}` to strings, and _that_ fails when I move the code to within a function. There seems to be some gotcha related to references. What’s the proper way to encapsulate that code, creating a handy `getstr` or something similar?

Here’s my C code

```julia
#include<stdint.h>
#include<stdio.h>

struct MyStruct {
  char name[16];
  uint8_t ipaddress[4];
  double xyz;
};

int writedata(struct MyStruct * buffer, int * buffersize) {
  *buffersize = *buffersize >> 1;
  for (int i = 0 ; i< *buffersize; i++) {
    int j = 0;
    for (; j<3; j++)
      buffer[i].name[j] = 'a' + j + (j+1)*i;
    buffer[i].name[j] = 0;
    buffer[i].ipaddress[0] = 192;
    buffer[i].ipaddress[1] = 168;
    buffer[i].ipaddress[2] = 0;
    buffer[i].ipaddress[3] = 128 + i;
    buffer[i].xyz = i*i*3.1415;
  }
  return (*buffersize > 0) ? 0 : 1;
}

int main(int argc, char** argv) {
  struct MyStruct mydata[8];
  int buffersize = 8;
  writedata(mydata, &buffersize);
  for (int i; i < buffersize; i++) {
    printf("%s - %d.%d.%d.%d - %f\n",
	   mydata[i].name,
	   mydata[i].ipaddress[0], mydata[i].ipaddress[1], mydata[i].ipaddress[2], mydata[i].ipaddress[3],
	   mydata[i].xyz);
  }
}

/* gcc testapi.c -o testapi.so -shared -fPIC */

```

And the Julia code

```julia
struct MyStruct
    name ::NTuple{16, UInt8}
    ipaddress ::NTuple{4, UInt8}
    xyz ::Float64
end

# getstr(x) = unsafe_string(Ptr{UInt8}(pointer_from_objref(Ref(x))))
getstr(x) = unsafe_string(Ptr{UInt8}(pointer_from_objref(x)))
# getstr(x) = Ptr{UInt8}(pointer_from_objref(x))
# getstr(x) = x

function api_writedata(buffer, buffersize)
    ccall(
        (:writedata, "testapi.so"),
        Cint,
        (Ptr{MyStruct}, Ptr{UInt32}),
        buffer, buffersize
    )
end 

mydata = Vector{MyStruct}(undef, 8)
buffersize = Ref(0x00000008)

api_writedata(mydata, buffersize)
for data in mydata[1:buffersize[]]
    # println("$(data.name) - $(join(data.ipaddress,'.')) - $(data.xyz)")
    println("$(getstr(Ref(data.name))) - $(join(data.ipaddress,'.')) - $(data.xyz)")
end
println("***")

function process()
    mydata = Vector{MyStruct}(undef, 8)
    buffersize = Ref(0x00000008)

    api_writedata(mydata, buffersize)
    for data in mydata[1:buffersize[]]
        # println("$(data.name) - $(join(data.ipaddress,'.')) - $(data.xyz)")
        println("$(getstr(Ref(data.name))) - $(join(data.ipaddress,'.')) - $(data.xyz)")
    end
    
end

process()

```

The resulting output:

```julia
abc - 192.168.0.128 - 0.0
bdf - 192.168.0.129 - 3.1415
cfi - 192.168.0.130 - 12.566
dhl - 192.168.0.131 - 28.273500000000002
***
 - 192.168.0.128 - 0.0
 - 192.168.0.129 - 3.1415
 - 192.168.0.130 - 12.566
 - 192.168.0.131 - 28.273500000000002

```

---

_[View the full topic](https://discourse.julialang.org/t/ccall-works-on-global-scope-but-not-within-function/72119)._
