I’m working on wrapping some C code, and one of the fundamental objects in the library is an array of function pointers. I can obtain a pointer to the object with dlsym
fine, but when I try to wrap the pointer into an array I get a ReadOnlyMemoryError()
and Julia crashes.
Here is a minimal example (not runnable b.c. Lints isn’t registered yet).
julia> using Lints
julia> using Libdl
julia> Lints.init()
julia> X = dlsym(Lints.libint2,:libint2_build_eri)
Ptr{Nothing} @0x00007f1c494fab80
julia> unsafe_wrap(Array,reinterpret(Ptr{Function},X),(7,7,7,7))
Internal error: encountered unexpected error in runtime:
ReadOnlyMemoryError()
[huge stacktrace]
Any ideas about how to work with such an object (C array of function pointers that I need to pass to ccall
).
You’re not far off, but you need to make a couple of changes. First of all, Ptr{Function}
isn’t the right type: that would be a pointer to the Julia abstract type Function
, which isn’t the same as a C function. Second, you have an array of function pointers, so you need to treat it as a pointer-to-pointer-to-function.
For bonus points, here’s a complete working example because I’m still waiting for my non-Julia code to compile at work:
julia> C_code = """
int times_two(int x) {
return x * 2;
}
int times_three(int x) {
return x * 3;
}
int (*functions[2])(int) = {times_two, times_three};
""";
julia> using Libdl
julia> const Clib = tempname() * "." * Libdl.dlext
"/tmp/jl_S95rOT.so"
julia> open(`gcc -fPIC -O3 -msse3 -xc -shared -o $Clib -`, "w") do cmd
print(cmd, C_code)
end
julia> lib = Libdl.dlopen(Clib)
Ptr{Nothing} @0x0000000000dece20
julia> X = dlsym(lib,:functions)
Ptr{Nothing} @0x00007f4968c50030
julia> functions = unsafe_wrap(Array, reinterpret(Ptr{Ptr{Cvoid}}, X), 2)
2-element Array{Ptr{Nothing},1}:
Ptr{Nothing} @0x00007f4968a4f600
Ptr{Nothing} @0x00007f4968a4f610
julia> ccall(functions[1], Cint, (Cint,), 2)
4
julia> ccall(functions[2], Cint, (Cint,), 2)
6
3 Likes
Ah, I see now. Still getting the hang of working with the C interface. Thank you!