Skip to content

Commit

Permalink
Add cfunction tuple of types deprecation (#23066)
Browse files Browse the repository at this point in the history
* Add cfunction tuple of types deprecation

* Update docs
  • Loading branch information
musm authored and KristofferC committed Aug 23, 2017
1 parent f321fee commit b330b0e
Show file tree
Hide file tree
Showing 12 changed files with 30 additions and 28 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ 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]).

* `diagm(A::SparseMatrixCSC)` has been deprecated in favor of
`spdiagm(sparsevec(A))` ([#23341]).

Expand Down
3 changes: 3 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1713,6 +1713,9 @@ export hex2num
# issue #17886
# deprecations for filter[!] with 2-arg functions are in associative.jl

# PR #23066
@deprecate cfunction(f, r, a::Tuple) cfunction(f, r, Tuple{a...})

# PR 23341
@deprecate diagm(A::SparseMatrixCSC) spdiagm(sparsevec(A))

Expand Down
6 changes: 3 additions & 3 deletions doc/src/manual/calling-c-and-fortran-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ Julia function. Arguments to [`cfunction()`](@ref) are as follows:
1. A Julia Function
2. Return type
3. A tuple of input types
3. A tuple type of input types
Only platform-default C calling convention is supported. `cfunction`-generated pointers cannot
be used in calls where WINAPI expects `stdcall` function on 32-bit windows, but can be used on WIN64
Expand Down Expand Up @@ -192,11 +192,11 @@ a C `int`, so we must be sure to return `Cint` via a call to `convert` and a `ty
In order to pass this function to C, we obtain its address using the function `cfunction`:

```jldoctest mycompare
julia> const mycompare_c = cfunction(mycompare, Cint, (Ref{Cdouble}, Ref{Cdouble}));
julia> const mycompare_c = cfunction(mycompare, Cint, Tuple{Ref{Cdouble}, Ref{Cdouble}});
```

[`cfunction()`](@ref) accepts three arguments: the Julia function (`mycompare`), the return type
(`Cint`), and a tuple of the argument types, in this case to sort an array of `Cdouble`
(`Cint`), and a tuple type of the input argument types, in this case to sort an array of `Cdouble`
([`Float64`](@ref)) elements.

The final call to `qsort` looks like this:
Expand Down
2 changes: 1 addition & 1 deletion examples/embedding/embedding.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ int main()
" nothing\n"
"end");
typedef void (*Func_VOID__VOID)(void);
jl_value_t *pbar = jl_eval_string("cfunction(bar_from_c, Void, ())");
jl_value_t *pbar = jl_eval_string("cfunction(bar_from_c, Void, Tuple{})");
Func_VOID__VOID bar = (Func_VOID__VOID)jl_unbox_voidpointer(pbar);
bar();
checked_eval_string("bar() = println(\"calling new bar\")");
Expand Down
4 changes: 0 additions & 4 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1422,10 +1422,6 @@ extern "C" JL_DLLEXPORT
void *jl_function_ptr(jl_function_t *f, jl_value_t *rt, jl_value_t *argt)
{
JL_GC_PUSH1(&argt);
if (jl_is_tuple(argt)) {
// TODO: maybe deprecation warning, better checking
argt = (jl_value_t*)jl_apply_tuple_type_v((jl_value_t**)jl_data_ptr(argt), jl_nfields(argt));
}
JL_LOCK(&codegen_lock);
Function *llvmf = jl_cfunction_object(f, rt, (jl_tupletype_t*)argt);
JL_GC_POP();
Expand Down
4 changes: 2 additions & 2 deletions test/ambiguous.jl
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,15 @@ end
# Test that non-ambiguous cases work
io = IOBuffer()
@test precompile(ambig, (Int, Int)) == true
cfunction(ambig, Int, (Int, Int))
cfunction(ambig, Int, Tuple{Int, Int})
@test length(code_lowered(ambig, (Int, Int))) == 1
@test length(code_typed(ambig, (Int, Int))) == 1
code_llvm(io, ambig, (Int, Int))
code_native(io, ambig, (Int, Int))

# Test that ambiguous cases fail appropriately
@test precompile(ambig, (UInt8, Int)) == false
cfunction(ambig, Int, (UInt8, Int)) # test for a crash (doesn't throw an error)
cfunction(ambig, Int, Tuple{UInt8, Int}) # test for a crash (doesn't throw an error)
@test_throws ErrorException which(ambig, (UInt8, Int))
@test_throws ErrorException code_llvm(io, ambig, (UInt8, Int))
@test_throws ErrorException code_native(io, ambig, (UInt8, Int))
Expand Down
24 changes: 12 additions & 12 deletions test/ccall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -791,57 +791,57 @@ for (t,v) in ((Complex{Int32},:ci32),(Complex{Int64},:ci64),
function $fname(s)
@assert false
end
b = ccall(cfunction($fname1,Ref{$t},(Ref{$t},)),Ref{$t},(Ref{$t},),a)
b = ccall(cfunction($fname1, Ref{$t}, Tuple{Ref{$t}}), Ref{$t}, (Ref{$t},), a)
verbose && println("C: ",b)
@test b == $v
@test b === a
@test b === c
b = ccall(cfunction($fname,$t,($t,)),$t,($t,),a)
b = ccall(cfunction($fname, $t, Tuple{$t}), $t, ($t,), a)
verbose && println("C: ",b)
@test b == $v
if ($(t).mutable)
@test !(b === c)
@test !(b === a)
end
b = ccall(cfunction($fname1,$t,(Ref{$t},)),$t,(Ref{$t},),a)
b = ccall(cfunction($fname1, $t, Tuple{Ref{$t}}), $t, (Ref{$t},), a)
verbose && println("C: ",b)
@test b == $v
if ($(t).mutable)
@test !(b === c)
@test !(b === a)
end
b = ccall(cfunction($fname,Ref{$t},($t,)),Ref{$t},($t,),a)
b = ccall(cfunction($fname, Ref{$t}, Tuple{$t}), Ref{$t}, ($t,), a)
verbose && println("C: ",b)
@test b == $v
@test b === c
if ($(t).mutable)
@test !(b === a)
end
b = ccall(cfunction($fname,Any,(Ref{$t},)),Any,(Ref{$t},),$v)
b = ccall(cfunction($fname, Any, Tuple{Ref{$t}}), Any, (Ref{$t},), $v)
verbose && println("C: ",b)
@test b == $v
@test b === c
if ($(t).mutable)
@test !(b === a)
end
b = ccall(cfunction($fname,Any,(Ref{Any},)),Any,(Ref{Any},),$v)
b = ccall(cfunction($fname, Any, Tuple{Ref{Any}}), Any, (Ref{Any},), $v)
@test b == $v
@test b === c
if ($(t).mutable)
@test !(b === a)
end
@test_throws TypeError ccall(cfunction($fname,Ref{AbstractString},(Ref{Any},)),Any,(Ref{Any},),$v)
@test_throws TypeError ccall(cfunction($fname,AbstractString,(Ref{Any},)),Any,(Ref{Any},),$v)
@test_throws TypeError ccall(cfunction($fname, Ref{AbstractString}, Tuple{Ref{Any}}), Any, (Ref{Any},), $v)
@test_throws TypeError ccall(cfunction($fname, AbstractString, Tuple{Ref{Any}}), Any, (Ref{Any},), $v)
end
end

# issue 13031
foo13031(x) = Cint(1)
foo13031p = cfunction(foo13031, Cint, (Ref{Tuple{}},))
foo13031p = cfunction(foo13031, Cint, Tuple{Ref{Tuple{}}})
ccall(foo13031p, Cint, (Ref{Tuple{}},), ())

foo13031(x,y,z) = z
foo13031p = cfunction(foo13031, Cint, (Ref{Tuple{}},Ref{Tuple{}},Cint))
foo13031p = cfunction(foo13031, Cint, Tuple{Ref{Tuple{}}, Ref{Tuple{}}, Cint})
ccall(foo13031p, Cint, (Ref{Tuple{}},Ref{Tuple{}},Cint), (), (), 8)

# issue 17219
Expand Down Expand Up @@ -993,7 +993,7 @@ if Sys.ARCH === :x86_64
T = NTuple{4, VecElement{s}}
@eval function rt_sse(a1::$T, a2::$T, a3::$T, a4::$T)
return ccall(
cfunction(foo_ams, $T, ($T, $T, $T, $T)),
cfunction(foo_ams, $T, Tuple{$T, $T, $T, $T}),
$T,
($T, $T, $T, $T),
a1, a2, a3, a4)
Expand Down Expand Up @@ -1281,7 +1281,7 @@ end
evalf_callback_19805(ci::callinfos_19805{FUNC_FT}) where {FUNC_FT} = ci.f(0.5)::Float64

evalf_callback_c_19805(ci::callinfos_19805{FUNC_FT}) where {FUNC_FT} = cfunction(
evalf_callback_19805, Float64, (callinfos_19805{FUNC_FT},))
evalf_callback_19805, Float64, Tuple{callinfos_19805{FUNC_FT}})

@test_throws(ErrorException("ccall: the type of argument 1 doesn't correspond to a C type"),
evalf_callback_c_19805( callinfos_19805(sin) ))
Expand Down
2 changes: 1 addition & 1 deletion test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4404,7 +4404,7 @@ end
function f18054()
return Cint(0)
end
cfunction(f18054, Cint, ())
cfunction(f18054, Cint, Tuple{})

# issue #18986: the ccall optimization of cfunction leaves JL_TRY stack in bad state
dummy18996() = return nothing
Expand Down
2 changes: 1 addition & 1 deletion test/misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ if Sys.iswindows()
x+y
end

let addr = cfunction(WeVirtualProtectThisToRWX, UInt64, (UInt64, UInt64))
let addr = cfunction(WeVirtualProtectThisToRWX, UInt64, Tuple{UInt64, UInt64})
addr = addr-(UInt64(addr)%4096)
PAGE_EXECUTE_READWRITE = 0x40
oldPerm = Ref{UInt32}()
Expand Down
4 changes: 2 additions & 2 deletions test/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ end
tracefoo(x, y) = x+y
didtrace = false
tracer(x::Ptr{Void}) = (@test isa(unsafe_pointer_to_objref(x), Core.MethodInstance); global didtrace = true; nothing)
ccall(:jl_register_method_tracer, Void, (Ptr{Void},), cfunction(tracer, Void, (Ptr{Void},)))
ccall(:jl_register_method_tracer, Void, (Ptr{Void},), cfunction(tracer, Void, Tuple{Ptr{Void}}))
meth = which(tracefoo,Tuple{Any,Any})
ccall(:jl_trace_method, Void, (Any,), meth)
@test tracefoo(1, 2) == 3
Expand All @@ -508,7 +508,7 @@ ccall(:jl_register_method_tracer, Void, (Ptr{Void},), C_NULL)

# Method Tracing test
methtracer(x::Ptr{Void}) = (@test isa(unsafe_pointer_to_objref(x), Method); global didtrace = true; nothing)
ccall(:jl_register_newmeth_tracer, Void, (Ptr{Void},), cfunction(methtracer, Void, (Ptr{Void},)))
ccall(:jl_register_newmeth_tracer, Void, (Ptr{Void},), cfunction(methtracer, Void, Tuple{Ptr{Void}}))
tracefoo2(x, y) = x*y
@test didtrace
didtrace = false
Expand Down
2 changes: 1 addition & 1 deletion test/spawn.jl
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ let fname = tempname()
oldhandle = OLD_STDERR.handle
OLD_STDERR.status = Base.StatusClosing
OLD_STDERR.handle = C_NULL
ccall(:uv_close, Void, (Ptr{Void}, Ptr{Void}), oldhandle, cfunction(thrash, Void, (Ptr{Void},)))
ccall(:uv_close, Void, (Ptr{Void}, Ptr{Void}), oldhandle, cfunction(thrash, Void, Tuple{Ptr{Void}}))
sleep(1)
import Base.zzzInvalidIdentifier
"""
Expand Down
2 changes: 1 addition & 1 deletion test/staged.jl
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ module TestGeneratedThrow
foo() = (bar(rand() > 0.5 ? 1 : 1.0); error("foo"))
function __init__()
code_typed(foo,(); optimize = false)
cfunction(foo,Void,())
cfunction(foo,Void,Tuple{})
end
end

Expand Down

0 comments on commit b330b0e

Please sign in to comment.