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 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
#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
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:
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