@cfunction cannot find function defined in the same module

I’d like to use a function f() defined in a module as a callback in another function g() in the same module. However, I encountered this error:

ERROR: LoadError: UndefVarError: f not defined.

moving the definition of function f() before the definition g() does make it work.

I googled a bit and tried adding ‘$’ before f() in @cfunction, by doing this, the file can be included without error, but still fail to run and the REPL complained about type mismatch between ::Base.CFunction and ::Ptr{Nothing}.

Please help me out this situation. Thank you.

Julia Version 1.2.0
Commit c6da87ff4b (2019-08-20 00:03 UTC)
Platform Info:
OS: Windows (x86_64-w64-mingw32)
CPU: Intel(R) Xeon(R) CPU X5670 @ 2.93GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-6.0.1 (ORCJIT, westmere)

Hi,
I can’t quite tell what you’re trying to do. Are you trying to pass the function f as an input to the function g? Or are you just trying to call f from inside g? It’s a bit hard to help without knowing a little more about your situation. Are you able to post a minimal working example?

Also, is this all happening inside julia or are you trying to call julia from C? I’m asking because you’ve mentioned the use of @cfunction.

1 Like

Thank you for your reply. I was trying to use a self-defined function as a callback for a C-function.
Here is a example that can re produce the error:

module TestModule

function TestCallBackFunc(f::Ptr{Cvoid}, x, y)
    return ccall(f, Cint, (Cint, Cint), x, y)
end

function g()
    return TestCallBackFunc(@cfunction(f, Cint, (Cint, Cint)), 1, 2)
end

function f(a::Cint, b::Cint)::Cint
    return (a > b) ? -1 : 1
end

end

include this file would raise error:

julia> include("TestModule.jl")
ERROR: LoadError: UndefVarError: f not defined

However, simply moving the definition of f() would make it work.

module TestModule

function f(a::Cint, b::Cint)::Cint
    return (a > b) ? -1 : 1
end

function TestCallBackFunc(f::Ptr{Cvoid}, x, y)
    return ccall(f, Cint, (Cint, Cint), x, y)
end

function g()
    return TestCallBackFunc(@cfunction(f, Cint, (Cint, Cint)), 1, 2)
end

end
julia> include("TestModule.jl")
Main.TestModule
julia> TestModule.g()
1
1 Like

I think that is the intended behaviour. I think you need to define the function f before referencing it, even if it’s in the same module.
Edit: Interesting. For regular julia functions the following works

julia> module myMod

       g(x) = f(x) + 2
       f(x) = x^2
       end
Main.myMod

julia> using .myMod

julia> myMod.g(2)
6

I’m not sure why the @cfunction macro f to be defined before it’s referenced. Interesting. In any event, my workaround still works:

You don’t need to define all the methods you need in advance. So if for some reason you want/need to define your f(a::Cint, b::Cint)::Cint method after your g() method you can do the following

julia> module TestModule
       export f,g
       function f end
       function TestCallBackFunc(f::Ptr{Cvoid}, x, y)
           return ccall(f, Cint, (Cint, Cint), x, y)
       end

       function g()
           return TestCallBackFunc(@cfunction(f, Cint, (Cint, Cint)), 1, 2)
       end

       function f(a::Cint, b::Cint)::Cint
           return (a > b) ? -1 : 1
       end
       end

Main.TestModule

julia> using .TestModule

julia> g()
1
1 Like