# C Interface -- Library name must be a constant expression?

**URL:** https://discourse.julialang.org/t/c-interface-library-name-must-be-a-constant-expression/22171
**Category:** General Usage
**Created:** [March 21, 2019, 9:55pm UTC](https://discourse.julialang.org/t/c-interface-library-name-must-be-a-constant-expression/22171 "2019-03-21T21:55:48Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![danielc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielc/32/220_2.png) [@danielc](https://discourse.julialang.org/u/danielc)
#### Post date: [March 21, 2019, 9:55pm UTC](https://discourse.julialang.org/t/c-interface-library-name-must-be-a-constant-expression/22171/1 "2019-03-21T21:55:48Z")

</div>

I’m calling a C function:

```julia
LIBTTV = "path/to/library.so"
ccall( (:TTVFast, LIBTTV), Cvoid, ... )

```

This gives an error:

```julia
ERROR: LoadError: TypeError: in top-level scope, in ccall:
first argument not a pointer or valid constant expression,
expected Ptr, got Tuple{Symbol,String}

```

If I replace `LIBTTV` with the actual string:

```julia
ccall( (:TTVFast, "path/to/library.so"), Cvoid, ... )

```

The call works correctly.

Now, this is a little weird. Why does the path to the library need to be a constant? Needless to say, hard-coding a path is bad form. I want to use `Libdl` to find the correct path to the library. I can’t imagine that this is intended behaviour. Is there something that I’m doing wrong? How can I put the path to the library in a variable?

Thanks for the help.

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [March 21, 2019, 10:11pm UTC](https://discourse.julialang.org/t/c-interface-library-name-must-be-a-constant-expression/22171/2 "2019-03-21T22:11:18Z")

</div>

This is entirely desired behavior. You should look for the library and hard code it at build time. For one time script, just use a const global variable for the name since there isn’t a distinction between build time and runtime there.

If you must look for the library at runtime, you need to switch to dlopen and dlsym explicitly.

---

<div class="post-metadata">

### Author: ![danielc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielc/32/220_2.png) [@danielc](https://discourse.julialang.org/u/danielc)
#### Post date: [March 21, 2019, 11:52pm UTC](https://discourse.julialang.org/t/c-interface-library-name-must-be-a-constant-expression/22171/3 "2019-03-21T23:52:11Z")

</div>

What exactly do you mean by “hard code it at build time”? This is a script. There is no “build time”.

Also, a function cannot make a `global const` variable. So apparently the only option is to de-modularize the code. It’s annoying that the desired behaviour appears to be “broken”.

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [March 22, 2019, 12:41am UTC](https://discourse.julialang.org/t/c-interface-library-name-must-be-a-constant-expression/22171/4 "2019-03-22T00:41:34Z")

</div>

> [@danielc](#):
>
> What exactly do you mean by “hard code it at build time”? This is a script. There is no “build time”.

Well, as I said, for a one time script, the build time and the run time are the same.

> [@danielc](#):
>
> function cannot make a `global const` variable

For one, that’s not true, but yes, you need to determine the name before you use the function.

> [@danielc](#):
>
> So apparently the only option is to de-modularize the code

There’s nothing non modular about it.

> [@danielc](#):
>
> It’s annoying that the desired behaviour appears to be “broken”.

That’s because (edited:) your interpretation of the desired behavior or your definition of broken is wrong. What you are thinking is likely the C dlopen behavior. But ccall is not a function, it’s a syntax exactly the same as writing normal function calls in C. What you want does not work for the same reason `const char *name = "sin"; double f(double) asm(name); f(1.0);` doesn’t work as you need a compile time constant there as the symbol name (and since Julia allows you to explicitly specify the lib name, that as well).

What you want corresponds to C dlopen which will work exactly the same in Julia with basically the same function names. You do not get address memorization automatically, since the lookup logic can be arbitrary code and it’s impossible for the compiler to keep track of, again, same as c. If you have some specific pattern, you can create a memorized version of dlsym easily, I believe pycall has one implementation. If this is what you mean by modularize then you should just do that.

Note that I use C as example but it could really be any language with a similar interface.

---

<div class="post-metadata">

### Author: ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)
#### Post date: [March 22, 2019, 1:05am UTC](https://discourse.julialang.org/t/c-interface-library-name-must-be-a-constant-expression/22171/5 "2019-03-22T01:05:48Z")

</div>

The better way to do this is `ccall( (:TTVFast, "library.so"), Cvoid, ... )` and then make sure `"library.so"` is in your `LD_LIBRARY_PATH`. This will make your script work on different systems too where the path might be different and each can have its own `LD_LIBRARY_PATH`.

If its really important that its specifiable via an argument, you could use a generated function, which effectively “moves it to build-time” like @yuyichao suggests, I think something like the following will work:

```julia
call_TTVFast(LIBTTV::String) = call_TTVFast(Val(Symbol(LIBTTV)))

@generated function call_TTVFast(::Val{LIBTTV}) where {LIBTTV}
    quote 
        ccall( (:TTVFast, $(String(LIBTTV))), Cvoid, ...)
    end
end

call_TTVFast("/path/to/library.so")

```

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [March 22, 2019, 1:12am UTC](https://discourse.julialang.org/t/c-interface-library-name-must-be-a-constant-expression/22171/6 "2019-03-22T01:12:44Z")

</div>

> [@marius311](#):
>
> If its really important that its specifiable via an argument, you could use a generated function, which effectively “moves it to build-time” like @yuyichao suggests, I think something like the following will work:

Don’t call the compiler for the sake of calling the compiler. This will give you a performance worse than doing a `Dict{String,Ptr{Cvoid}}` lookup as memorization.

---

<div class="post-metadata">

### Author: ![danielc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielc/32/220_2.png) [@danielc](https://discourse.julialang.org/u/danielc)
#### Post date: [March 22, 2019, 1:22am UTC](https://discourse.julialang.org/t/c-interface-library-name-must-be-a-constant-expression/22171/7 "2019-03-22T01:22:57Z")

</div>

> [@yuyichao](#):
>
> > [@danielc](#):
> >
> > function cannot make a `global const` variable
> 
> For one, that’s not true, but yes, you need to determine the name before you use the function.

Why doesn’t it work for me? Am I doing something wrong?:

```julia
julia> function foo()
           global const x = 3
       end
ERROR: syntax: `global const` declaration not allowed
inside function around REPL[1]:2

```

> [@yuyichao](#):
>
> But ccall is not a function, it’s a syntax exactly the same as writing normal function calls in C.

Thanks for the clarification. I did think that `ccall` was a function.

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [March 22, 2019, 1:24am UTC](https://discourse.julialang.org/t/c-interface-library-name-must-be-a-constant-expression/22171/8 "2019-03-22T01:24:42Z")

</div>

> [@danielc](#):
>
> Why doesn’t it work for me? Am I doing something wrong?:

Use `eval`. It indeed does not allow you to do what you want in the same function since you still

> [@danielc](#):
>
> need to determine the name before you use the function

However, you don’t need to put all those code in global scope. Your (“build time”) initialization code can be a function. Purely from a code organization point of view.

> [@danielc](#):
>
> I did think that `ccall` was a function.

I had the same confusion initially so I’m not surprized…

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [March 22, 2019, 1:45am UTC](https://discourse.julialang.org/t/c-interface-library-name-must-be-a-constant-expression/22171/9 "2019-03-22T01:45:39Z")

</div>

Yeah, `ccall` probably should use macro syntax but it predates macros.

---

<div class="post-metadata">

### Author: ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)
#### Post date: [March 22, 2019, 6:02am UTC](https://discourse.julialang.org/t/c-interface-library-name-must-be-a-constant-expression/22171/10 "2019-03-22T06:02:35Z")

</div>

[Here](https://docs.julialang.org/en/v1/stdlib/Libdl/index.html) is the documentation on Libdl, for dynamic linking. [Libdl.dlopen](https://docs.julialang.org/en/v1/stdlib/Libdl/index.html#Libdl.dlopen) the library, and [Libdl.dlsym](https://docs.julialang.org/en/v1/stdlib/Libdl/index.html#Libdl.dlsym) to get function pointers that work with ccall.

```julia
julia> using Libdl

julia> libc = dlopen("/usr/lib/libc.so.6")
Ptr{Nothing} @0x00007f45f0a783f0

julia> clock_pointer = dlsym(libc, :clock)
Ptr{Nothing} @0x00007f45f0396f80

julia> noargccall(function_pointer) = ccall(function_pointer, Int32, ())
noargccall (generic function with 1 method)

julia> noargccall(clock_pointer)
5177952

julia> noargccall(clock_pointer)
5328805

```
