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.

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.

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")