diff --git a/NEWS.md b/NEWS.md index 3ce11e7fe2c25..ca824e1c684bf 100644 --- a/NEWS.md +++ b/NEWS.md @@ -996,8 +996,11 @@ Deprecated or removed * `Base.SparseArrays.SpDiagIterator` has been removed ([#23261]). - * The tuple-of-types form of `cfunction`, `cfunction(f, returntype, (types...))`, has been deprecated - in favor of the tuple-type form `cfunction(f, returntype, Tuple{types...})` ([#23066]). + * The function `cfunction`, has been deprecated in favor of a macro form `@cfunction`. + Most existing uses can be upgraded simply by adding a `@`. + The new syntax now additionally supports allocating closures at runtime, + for dealing with C APIs that don't provide a separate `void* env`-type callback + argument. ([#26486]) * `diagm(v::AbstractVector, k::Integer=0)` has been deprecated in favor of `diagm(k => v)` ([#24047]). diff --git a/base/c.jl b/base/c.jl index b369a5e11a073..21994d835a0d5 100644 --- a/base/c.jl +++ b/base/c.jl @@ -16,12 +16,22 @@ respectively. """ cglobal -struct CFunction +""" + CFunction struct + +Garbage-collection handle for the return value from `@cfunction` +when the first argument is annotated with '\$'. +Like all `cfunction` handles, it should be passed to `ccall` as a `Ptr{Cvoid}`, +and will be converted automatically at the call site to the appropriate type. + +See [`@cfunction`](@ref). +""" +struct CFunction <: Ref{Cvoid} ptr::Ptr{Cvoid} f::Any _1::Ptr{Cvoid} _2::Ptr{Cvoid} - let construtor = false end + let constructor = false end end unsafe_convert(::Type{Ptr{Cvoid}}, cf::CFunction) = cf.ptr @@ -31,11 +41,12 @@ unsafe_convert(::Type{Ptr{Cvoid}}, cf::CFunction) = cf.ptr Generate a C-callable function pointer from the Julia function `closure` for the given type signature. +To pass the return value to a `ccall`, use the argument type `Ptr{Cvoid}` in the signature. Note that the argument type tuple must be a literal tuple, and not a tuple-valued variable or expression (although it can include a splat expression). And that these arguments will be evaluated in global scope during compile-time (not deferred until runtime). -Adding a `\$` in front of the function argument changes this to instead create a runtime closure +Adding a '\$' in front of the function argument changes this to instead create a runtime closure over the local variable `callable`. See [manual section on ccall and cfunction usage](@ref Calling-C-and-Fortran-Code). diff --git a/base/compiler/validation.jl b/base/compiler/validation.jl index 01c7abcdc1640..1d12dc8e3d333 100644 --- a/base/compiler/validation.jl +++ b/base/compiler/validation.jl @@ -22,7 +22,7 @@ const VALID_EXPR_HEADS = IdDict{Any,Any}( :meta => 0:typemax(Int), :global => 1:1, :foreigncall => 3:typemax(Int), - :cfunction => 6:6, + :cfunction => 5:5, :isdefined => 1:1, :simdloop => 0:0, :gc_preserve_begin => 0:typemax(Int), diff --git a/doc/src/base/c.md b/doc/src/base/c.md index a09b916c7d726..7977dd2ea36e1 100644 --- a/doc/src/base/c.md +++ b/doc/src/base/c.md @@ -4,6 +4,7 @@ ccall Core.Intrinsics.cglobal Base.@cfunction +Base.CFunction Base.unsafe_convert Base.cconvert Base.unsafe_load