I am extending a Julia package that uses a C library. I need to call some C functions from Julia. They look something like this:
struct contained {
int x;
int y;
int z;
};
struct mystruct {
int n;
contained* arr;
};
mystruct* mk_mystruct(int n, contained* arr);
void use_mystruct(mystruct* foo);
I have also declared the corresponding types in Julia:
type contained
x::Int64
y::Int64
z::Int64
end
type mystruct
n::Int64
arr::Array{contained, 1}
end
To ccall
functions which take a contained*
as an argument, everything works fine treating the contained*
as Ptr{Int64}
:
con = fill(0, 5, 3);
mys = ccall((:mk_mystruct, "mylib"), Ptr{mystruct}, (Int64, Ptr{Int64}), n, con)
I suppose this works because contained
has the same memory layout as an array of Int64s. This is also how it is done elsewhere in the Julia package. But the only way I know to check the value of the returned mystruct
is to dereference it with unsafe_load
, at which point Julia crashes from a segfault. What is the right way to dereference a pointer in Julia?
The C library also includes pretty-printing functions, so instead of dereferencing the pointer in Julia I could treat the pointer as opaque and pass it back to this C function:
void print_mystruct(mystruct* foo, FILE* outputfile)
In the C code, this is called with outputfile=stdout
. How would I set this up with ccall
? This obviously does not work:
ccall((:print_mystruct, "mylib"), Void, (Ptr{mystruct}, Ptr{Void}), mys, stdout)
What should I put instead of Ptr{Void}
and stdout
? How does Julia implement I/O in the C interface?
When you declare the type in Julia, you must declare the same types as C:
The Julia type
Array{contained, 1}
would correspond tojl_value_t*
in C and the Julia typeInt
would correspond tointptr_t
in C.I don't know of a platform-agnostic way to get a handle to
stdout
, as most platforms require expanding a C header macro to find out the real symbol name. For example, on macOS, it gets renamed to__stdoutp
:You may be interested in checking out the Clang.jl package which can automatically generate these definitions from parsing the header files.