# \`ccall\` on Windows \`could not load symbol. The specified procedure could not be found\`

**URL:** <https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291>\
**Category:** General Usage\
**Tags:** windows, ccall, c\
**Created:** [August 12, 2021, 7:58pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291 "2021-08-12T19:58:54Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![nlaws](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nlaws/32/22205_2.png) [@nlaws](https://discourse.julialang.org/u/nlaws)\
**Post date:** [August 12, 2021, 7:58pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/1 "2021-08-12T19:58:54Z")

</div>

I am loading in a custom C library and then calling functions with `@ccall`. Everything works fine on Apple and Linux with:

```julia
hdl = Libc.Libdl.dlopen("path/to/clibrary", Libc.Libdl.RTLD_GLOBAL)
wind_module = @ccall ssc_module_create("windpower"::Cstring)::Ptr{Cvoid}
...
Libc.Libdl.dlclose(hdl)

```

However, on Windows I get:

```julia
could not load symbol "ssc_module_create":
  The specified procedure could not be found. 

```

I saw this same error on Linux before adding `Libc.Libdl.RTLD_GLOBAL` to `Libc.Libdl.dlopen`.

I’ve scoured the internet for a solution but nothing has come up. Anybody now how to make this work on Windows?

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [August 13, 2021, 12:50am UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/2 "2021-08-13T00:50:00Z")

</div>

Does the library export the symbol? For example, on Linux what’s the output of

```julia
nm /path/to/lib.so | grep ssc_module_create

```

?

---

<div class="post-metadata">

**Author:** ![nlaws](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nlaws/32/22205_2.png) [@nlaws](https://discourse.julialang.org/u/nlaws)\
**Post date:** [August 13, 2021, 3:57pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/3 "2021-08-13T15:57:03Z")

</div>

Yes I checked that on Linux and confirmed that all symbols are exported. How would one check that all symbols are exported on Windows?

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [August 13, 2021, 4:05pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/4 "2021-08-13T16:05:23Z")

</div>

I don’t know, I’m not familiar with Windows tools, I’d use [`BinaryBuilder.jl`](https://github.com/JuliaPackaging/BinaryBuilder.jl) for that 😄 or also [`ObjectFile.jl`](https://github.com/staticfloat/ObjectFile.jl)

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [August 13, 2021, 5:03pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/5 "2021-08-13T17:03:04Z")

</div>

> [@nlaws](#):
>
> Yes I checked that on Linux and confirmed that all symbols are exported.

BTW, why if the symbol is exported you had to dlopen it with `RTLD_GLOBAL`?

---

<div class="post-metadata">

**Author:** ![nlaws](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nlaws/32/22205_2.png) [@nlaws](https://discourse.julialang.org/u/nlaws)\
**Post date:** [August 13, 2021, 5:44pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/6 "2021-08-13T17:44:11Z")

</div>

I wish I knew why: just found it in another discourse topic as an aside, like “(on Linux you have to add `RTLD_GLOBAL`)”. I think that `RTLD_GLOBAL` is the default on Apple so it works without any flags.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [August 13, 2021, 11:59pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/7 "2021-08-13T23:59:43Z")

</div>

> [@nlaws](#):
>
> Yes I checked that on Linux and confirmed that all symbols are exported. How would one check that all symbols are exported on Windows?

That’s probably the key for this. On Windows not all symbols are exported by default from a library. Dependency Walker or [Depends](https://github.com/lucasg/Dependencies) let you see which symbols are exported.  
Other things that at times happens is that some dependency is not in Windows path and therefore can’t be found. The dependency tools mentioned above are your only friends.  
Let me just add that how fuzzy this might seems finding dependency hells on Windows is much easier than on \*nix.

---

<div class="post-metadata">

**Author:** ![nlaws](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nlaws/32/22205_2.png) [@nlaws](https://discourse.julialang.org/u/nlaws)\
**Post date:** [August 16, 2021, 9:16pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/8 "2021-08-16T21:16:04Z")

</div>

Thank you @joa-quim!

Unfortunately I do not have access to a Windows machine, but am relying on Github Actions to test the Julia package on Windows.

I have found a work-around, but I wonder if it indicates that there is a simpler solution?

The original problem is that calling the symbols directly fails:

```julia
wind_module = @ccall ssc_module_create("windpower"::Cstring)::Ptr{Cvoid}
could not load symbol "ssc_module_create":
  The specified procedure could not be found.

```

However, if I first load the symbol with `dlsym` then I can call it without an error:

```julia
ssc_module_create = Libc.Libdl.dlsym(hdl, :ssc_module_create)
wind_module = @ccall $ssc_module_create("windpower"::Cstring)::Ptr{Cvoid}

```

I tested this with setting and getting a parameter in the C module as well and it worked. So I guess the solution is to load all of the C functions in with `dlsym`?

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [August 16, 2021, 9:25pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/9 "2021-08-16T21:25:20Z")

</div>

Assuming `hdl` is the shared library,

```julia
@ccall hdl.ssc_module_create("windpower"::Cstring)::Ptr{Cvoid}

```

Maybe this explains why you had to `dlopen` the library with `RTLD_GLOBAL` on Linux: you were calling the the function wrong

> [@nlaws](#):
>
> Unfortunately I do not have access to a Windows machine

If you’re on Linux:

```julia
julia -e 'using BinaryBuilderBase; BinaryBuilderBase.runshell(Platform("x86_64", "windows"))'

```

gives you a shell where you can run `nm` on Windows shared libraries. Of course you need to install [`BinaryBuilderBase.jl`](https://github.com/JuliaPackaging/BinaryBuilderBase.jl) first

---

<div class="post-metadata">

**Author:** ![nlaws](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nlaws/32/22205_2.png) [@nlaws](https://discourse.julialang.org/u/nlaws)\
**Post date:** [August 16, 2021, 9:52pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/10 "2021-08-16T21:52:06Z")

</div>

Sure enough:

```julia
sandbox:${WORKSPACE} # nm ssc.dll 
/opt/x86_64-w64-mingw32/bin/x86_64-w64-mingw32-nm: ssc.dll: no symbols

```

Is there a way to install and run Julia in this shell from `BinaryBuilder.jl`? (I want to try your suggestion of `hdl.ssc_module_create` on Windows).

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [August 16, 2021, 10:04pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/11 "2021-08-16T22:04:16Z")

</div>

> [@nlaws](#):
>
> ```julia
> ssc.dll: no symbols
> 
> ```

~~Uhm, try `nm -D` maybe?~~

> [@nlaws](#):
>
> Is there a way to install and run Julia in this shell from `BinaryBuilder.jl` ?

No, you can’t run Windows executables from inside this shell, this is simply a small Alpine Linux environment where we have some tools for cross-compilation.

You can try using [Wine](https://www.winehq.org/): I once tried running Julia under Wine, it was an… interesting experience.

But if you can reproduce the error on GitHub Actions, you can [log into the runners](https://github.com/mxschmitt/action-tmate).

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [August 16, 2021, 10:27pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/12 "2021-08-16T22:27:37Z")

</div>

Also `objdump`:

```julia
sandbox:${WORKSPACE} # ${target}-objdump -t ssc.dll 

ssc.dll: file format pei-x86-64

SYMBOL TABLE:
no symbols

```

and [`ObjectFile.jl`](https://github.com/staticfloat/ObjectFile.jl):

```julia
julia> using ObjectFile

julia> readmeta("./ssc.dll") do oh
           symbol_name.(Symbols(oh))
       end
AbstractString[]

```

don’t see any symbols. Are you really sure you compiled this shared library correctly, exporting all symbols?

---

<div class="post-metadata">

**Author:** ![nlaws](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nlaws/32/22205_2.png) [@nlaws](https://discourse.julialang.org/u/nlaws)\
**Post date:** [August 16, 2021, 10:48pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/13 "2021-08-16T22:48:42Z")

</div>

> [@giordano](#):
>
> Assuming `hdl` is the shared library,
> 
> ```julia
> @ccall hdl.ssc_module_create("windpower"::Cstring)::Ptr{Cvoid}
> 
> ```

`hdl` is defined as:

```julia
hdl = Libc.Libdl.dlopen("ssc.dll")

```

I tried the syntax with `hdl` and `ccall` on Apple, but maybe I’m doing something wrong?

```julia
julia> hdl = Libc.Libdl.dlopen("libssc.dylib")
Ptr{Nothing} @0x00007fb4c0dcf330

julia> @ccall hdl.ssc_module_create("windpower"::Cstring)::Ptr{Cvoid}
ERROR: TypeError: in ccall, expected Symbol, got a value of type Ptr{Nothing}

julia> @ccall $(hdl.ssc_module_create)("windpower"::Cstring)::Ptr{Cvoid}
ERROR: type Ptr has no field ssc_module_create

julia> @ccall ssc_module_create("windpower"::Cstring)::Ptr{Cvoid}
Ptr{Nothing} @0x00007fb4c3fcec30

```

The last `ccall` works on Linux and Apple but not Windows.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [August 16, 2021, 10:51pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/14 "2021-08-16T22:51:34Z")

</div>

```julia
julia> hdl = "./libssc.so"
"./libssc.so"

julia> @ccall hdl.ssc_module_create("windpower"::Cstring)::Ptr{Cvoid}
Ptr{Nothing} @0x000056513091d1f0

```

See the example of `glib` in the [docstring of `@ccall`](https://docs.julialang.org/en/v1/base/c/#Base.@ccall). You can `ccall` without specifying the library name only functions that are in the global table

---

<div class="post-metadata">

**Author:** ![nlaws](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nlaws/32/22205_2.png) [@nlaws](https://discourse.julialang.org/u/nlaws)\
**Post date:** [August 17, 2021, 4:36pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/15 "2021-08-17T16:36:40Z")

</div>

I marked the `ObjectFile` check for exported symbols as the solution since it is the simplest way to check the exported symbols using Julia.

I did not know that you could call the library with just the path to library file. Are there any issues with memory leaks using this method as opposed to opening a handle to the library using `Libc.Libdl.dlopen` (and closing the handle with `Libc.Libdl.dlclose`)?

I did not compile the Windows dll but the person that did is asking “what compiler flags need to be set for it to export function names?” Do you know the answer to this or a source that I can review? I believe that the issue may be related to compiling with Visual Studio - but I heard that anecdotally.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [August 17, 2021, 4:59pm UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/16 "2021-08-17T16:59:30Z")

</div>

> [@nlaws](#):
>
> I did not know that you could call the library with just the path to library file. Are there any issues with memory leaks using this method as opposed to opening a handle to the library using `Libc.Libdl.dlopen` (and closing the handle with `Libc.Libdl.dlclose` )?

No. This is what all [JLL packages](https://github.com/JuliaBinaryWrappers) do: they `dlopen` the library at ` __init__ ` time (_without_ `RTLD_GLOBAL`), and then you call functions into them by specifying the names of the libraries (e.g. `ccall((:func_name, "lib_path"), ...)`, or the `@ccall` equivalent). No need to manually `dlclose` the libraries.

Note that `Libdl` is a standard library, you don’t need to qualify it with the `Libc` submodule of `Base`, but you need to add `Libdl` to your dependencies in case you go by this route.

> [@nlaws](#):
>
> I did not compile the Windows dll but the person that did is asking “what compiler flags need to be set for it to export function names?”

I may be wrong, I’m not super familiar with Windows, but I don’t think this is a compiler flag. In some cases you may need to explicitly mark functions to be exported, see for example [winapi - Exporting functions from a DLL with dllexport - Stack Overflow](https://stackoverflow.com/q/538134/2442087). The fact that compilers on Unix systems export by default all symbols doesn’t encourage me to dig into Windows-specific oddities 🙂

---

<div class="post-metadata">

**Author:** ![nlaws](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nlaws/32/22205_2.png) [@nlaws](https://discourse.julialang.org/u/nlaws)\
**Post date:** [August 19, 2021, 2:07am UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/17 "2021-08-19T02:07:49Z")

</div>

So… I have confirmed via [logging into the Github Action runner](https://github.com/mxschmitt/action-tmate) as you suggested that the string path to the library works with `ccall` on Windows in a Julia REPL (also confirmed on two other Windows machines). But something is up with using `ccall` and the Windows .dll _in a module_. I have:

1. defined the string path variable as `global hdl = nothing` at the module level.
2. Then in the calling function I have `global hdl = "path/to/ssc.dll"` (based off of OS).
3. But when I `@ccall hdl.function_name(...)` I get ` **ERROR:** UndefVarError: function_name not defined`.

Is there something wrong with this method? (It works on Linux and Apple). The [example in the documentation for calling external C libraries](https://docs.julialang.org/en/v1/base/c/#C-Interface) defines the string path as a `const`, but should I do that if I need to change the string path based on the OS?

---

<div class="post-metadata">

**Author:** ![nlaws](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nlaws/32/22205_2.png) [@nlaws](https://discourse.julialang.org/u/nlaws)\
**Post date:** [August 19, 2021, 3:10am UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/18 "2021-08-19T03:10:23Z")

</div>

Nevermind! I had a triple string block for taking notes on the `ccall` issues, which turns out was affecting my definition of the string path variable for Windows! Yargh!

---

<div class="post-metadata">

**Author:** ![Sole](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sole/32/202974_2.png) [@Sole](https://discourse.julialang.org/u/Sole)\
**Post date:** [January 3, 2025, 9:59am UTC](https://discourse.julialang.org/t/ccall-on-windows-could-not-load-symbol-the-specified-procedure-could-not-be-found/66291/19 "2025-01-03T09:59:59Z")

</div>

Even though it’s 2025, I had a similar problem today, after compiling the dynamic library using GCC in MSYS-UCRT64, everything worked fine 🤣 . BTW my main julia info is :

```julia
Julia Version 1.10.6
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, goldmont)

```

Hope this could be helpful to somebody else. 😃
