Passing a String with file name of shared library to ccall

I have a shared C library with its full name in ENV["LIBSIMC"]:

julia> ENV["LIBSIMC"]
"/home/paul/st/simc/bin/libsimc.so"

My call works fine with a literal constant, e.g.:

ccall((:logText, "/home/paul/st/simc/bin/libsimc.so"), Cvoid, (Cstring,), "something, something")

but it fails with library name in a String:

julia>   ccall((:logText, ENV["LIBSIMC"]), Cvoid, (Cstring,), "something, something")
ERROR: TypeError: in ccall: first argument not a pointer or valid constant expression, expected Ptr, got Tuple{Symbol,String}

How to fix it?

You can’t do that. The name and library to ccall has to be a constant. If there’s no way to determine the name at pre-compilation time, you should use dlopen and dlsym manually. I believe PyCall uses it.

3 Likes

Thank you. I can work around it. I tried a relative path and I was surprised by the failure:

julia> ccall((:shutdown, "~/st/simc/bin/libsimc.so"), Cvoid, ())
ERROR: could not load library "~/st/simc/bin/libsimc.so"
~/st/simc/bin/libsimc.so: cannot open shared object file: No such file or directory
Stacktrace:
 [1] top-level scope at ./REPL[2]:1

shell> file ~/st/simc/bin/libsimc.so
/home/paul/st/simc/bin/libsimc.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=e9c5bf2bd0401b726d2a37c3162c93951f6f5736, not stripped

You did not try a relative path. You tried a shell expansion. ~ is the absolute path to your home and it’s a shell function. Relative path does work but it won’t be relative to somewhere you want.

1 Like

For the sake of completeness and as an answer to future searches, here is the way to use a String for library path:

libPath = pwd()
push!(Base.DL_LOAD_PATH, libPath)
ccall((:logText, "libsimc.so"), Cvoid, (Cstring,), "something, something")
3 Likes