# Using \`symbol\` in \`ccall\`

**URL:** <https://discourse.julialang.org/t/using-symbol-in-ccall/135608>\
**Category:** General Usage\
**Created:** [February 13, 2026, 7:30am UTC](https://discourse.julialang.org/t/using-symbol-in-ccall/135608 "2026-02-13T07:30:40Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![f-fathurrahman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/f-fathurrahman/32/8847_2.png) [@f-fathurrahman](https://discourse.julialang.org/u/f-fathurrahman)\
**Post date:** [February 13, 2026, 7:30am UTC](https://discourse.julialang.org/t/using-symbol-in-ccall/135608/1 "2026-02-13T07:30:40Z")

</div>

Dear all

Suppose that I have this Fortran module in file named `MyModule.f90`:

```fortran
MODULE MyModule
  IMPLICIT NONE
  !
  REAL(8) :: x
  INTEGER :: Nsize
  REAL(8), ALLOCATABLE :: v(:)
END MODULE 

!-------------------------------
SUBROUTINE initialize_mymodule()
!-------------------------------
  USE MyModule
  IMPLICIT NONE
  integer :: i
  x = 1.23d0
  Nsize = 5
  if(.not. allocated(v)) then
    ALLOCATE( v(Nsize) )
    do i = 1,Nsize
      v(i) = 0.1d0 + i
    enddo 
  endif
  WRITE(*,*) 'MyModule is initialized'
END SUBROUTINE 

!-----------------------------
SUBROUTINE finalize_mymodule()
!-----------------------------
  USE MyModule
  IMPLICIT NONE
  !
  DEALLOCATE( v )
  WRITE(*,*) 'MyModule is finalized'
END SUBROUTINE

```

Build dynlib with `gfortran`:

```julia-auto
gfortran -fPIC -shared MyModule.f90 -o libmymodule.so

```

Call from Julia:

```julia
const MYLIB = "./libmymodule.so"
# XXX: must specifiy as path string

function load_allocatable_array(symbol::Symbol, T::DataType, shape)
    @assert T == Float64
    ptr = cglobal( (symbol, MYLIB), Ptr{T} )
    tmp = zeros(T, prod(shape))
    for ip in 1:prod(shape)
        tmp[ip] = unsafe_load(unsafe_load(ptr,1),ip)
    end
    return reshape(tmp, shape)
end

function get_x()
    return unsafe_load(cglobal( (:__mymodule_MOD_x, MYLIB), Float64 ))
end

function get_x_v2()
    symb = :__mymodule_MOD_x
    return unsafe_load(cglobal( (symb, MYLIB), Float64 ))
end

function get_x_v3()
    symb = :__mymodule_MOD_x
    ptr = cglobal((symb, MYLIB), Float64)
    return ptr
end

function get_Nsize()
    return unsafe_load(cglobal( (:__mymodule_MOD_nsize, MYLIB), Int32 )) |> Int64 
end

# Should be called only once
ccall( (:initialize_mymodule_, MYLIB), Cvoid, () )

x = get_x()
#x = get_x_v2() # will crash
#x = unsafe_load(get_x_v3()) # will also crash
println("x = ", x)

Nsize = get_Nsize()
symb = :__mymodule_MOD_v
v = load_allocatable_array(symb, Float64, (Nsize,))
println("v = ", v)

```

Why `get_x_v2()` crash? Any difference with `get_x()`. I thought that both are the same (?).

This is tested on WSL2 and Julia 1.12.1:

```julia-auto
julia> versioninfo()
Julia Version 1.12.1
Commit ba1e628ee49 (2025-10-17 13:02 UTC)
Build Info:
  Official https://julialang.org release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 16 × AMD Ryzen 7 5800H with Radeon Graphics
  WORD_SIZE: 64
  LLVM: libLLVM-18.1.7 (ORCJIT, znver3)
  GC: Built with stock GC
Threads: 1 default, 1 interactive, 1 GC (on 16 virtual cores)
Environment:
  JULIA_REVISE_POLL = 1

```

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [February 13, 2026, 10:30am UTC](https://discourse.julialang.org/t/using-symbol-in-ccall/135608/2 "2026-02-13T10:30:36Z")

</div>

> [@f-fathurrahman](#):
>
> Why `get_x_v2()` crash? Any difference with `get_x()`. I thought that both are the same (?).

This is a reasonable assumption and would be correct if all involved functions were normal functions. Unfortunately `cglobal` is bit magical and requires literal arguments. This is not super easy to find out but the docstring says

> cglobal((symbol, library) [, type=Cvoid])
> 
> Obtain a pointer to a global variable in a C-exported shared library, **specified exactly as in ccall**. Returns a Ptr{Type}, defaulting to Ptr{Cvoid} if no Type argument is supplied. The values can be read or written by unsafe\_load or unsafe\_store!, respectively.

and the note in the [ccall documentation](https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/#ccall-interface) says that they must be literal values, and points to an `eval` trick, which can sometimes be useful to work around this limitation.

That said, there may also be bugs involved. Specifically I tried to check what LLVM code was generated but

```julia-auto
@code_llvm get_x_v2()

```

gives a segmentation fault on Julia 1.12 but not on 1.10.

Edit: Crash reported in [code\_llvm crashes on non-literal in global · Issue #61019 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/61019).

---

<div class="post-metadata">

**Author:** ![f-fathurrahman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/f-fathurrahman/32/8847_2.png) [@f-fathurrahman](https://discourse.julialang.org/u/f-fathurrahman)\
**Post date:** [February 14, 2026, 12:39pm UTC](https://discourse.julialang.org/t/using-symbol-in-ccall/135608/3 "2026-02-14T12:39:57Z")

</div>

Thanks for the pointer. I think I should read the docs carefully. I guess the thing that suprised me is that Julia does not complaint that the arguments that I supplied are not literal values and just crashed.

Sorry if I’m raising another question, why is `cglobal` in `load_allocatable_array` working? Also, if i copy-pasted the content of `get_x_v2` to REPL (outside function definiton it works?

```julia-auto
julia> const MYLIB = "./libmymodule.so"
"./libmymodule.so"

julia> # XXX: must specifiy as path string

       function load_allocatable_array(symbol::Symbol, T::DataType, shape)
           @assert T == Float64
           ptr = cglobal( (symbol, MYLIB), Ptr{T} )
           tmp = zeros(T, prod(shape))
           for ip in 1:prod(shape)
               tmp[ip] = unsafe_load(unsafe_load(ptr,1),ip)
           end
           return reshape(tmp, shape)
       end;

julia> symb = :__mymodule_MOD_x;

julia> unsafe_load(cglobal( (symb, MYLIB), Float64 ))
0.0

julia> ccall( (:initialize_mymodule_, MYLIB), Cvoid, () )
 MyModule is initialized

julia> unsafe_load(cglobal( (symb, MYLIB), Float64 ))
1.23

```
