You’re hoping to create an expression that evaluates to 1) define a wrapped function, then 2) make a function pointer from it. That would work if step 2 was a normal function call; sequential execution is what they do. But @cfunction isn’t a function call, it’s a macro call, and those are expanded in the expression before evaluation even happens.
Many macro calls are designed to expand to function calls that do the real work, so the sequential behavior still happens. Let’s see what @cfunction does:
julia> @macroexpand begin
function foo(x::Int, y::Int) # docstring example
return x + y
end
@cfunction(foo, Int, (Int, Int))
end
quote
#= REPL[25]:2 =#
function foo(x::Int, y::Int)
#= REPL[25]:2 =#
#= REPL[25]:3 =#
return x + y
end
#= REPL[25]:5 =#
$(Expr(:cfunction, Ptr{Nothing}, :(:foo), :Int, :(Core.svec(Int, Int)), :(:ccall)))
end
@cfunction expands to a dedicated Expr, which is definitely not a function call (:call). @cfunction’s docstring mentions
… these arguments will be evaluated in global scope during compile-time
(not deferred until runtime)…
so the real work happens during evaluation but before the sequential execution (like how local/global statements still apply to a whole scope despite being written at the tail end of the expression). You’ll need to evaluate that wrapped function into the global scope, then try the @cfunction call in a separate top-level expression.
julia> begin
function foo(x::Int, y::Int)
return x + y
end
@cfunction(foo, Int, (Int, Int)) # macro call errors at compile-time
end
ERROR: UndefVarError: `foo` not defined in `Main`
Suggestion: check for spelling errors or missing imports.
julia> foo # "preceding" definition was not executed
ERROR: UndefVarError: `foo` not defined in `Main`
Suggestion: check for spelling errors or missing imports.
julia> function foo(x::Int, y::Int)
return x + y
end
foo (generic function with 1 method)
julia> @cfunction(foo, Int, (Int, Int))
Ptr{Nothing} @0x000001ddee99b6f0