Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ccall should allow the same type signatures as cfunction #2554

Closed
stevengj opened this issue Mar 13, 2013 · 3 comments
Closed

ccall should allow the same type signatures as cfunction #2554

stevengj opened this issue Mar 13, 2013 · 3 comments
Assignees
Labels
breaking This change will break code
Milestone

Comments

@stevengj
Copy link
Member

Commit d42bb6d updated cfunction to allow more type signatures, such as Function, which is great for callback routines in which the C caller passes through some arguments as void* through to the callback. However, the same arguments must currently be passed as Any to ccall, which is a bit counter-intuitive.

It would be nice if ccall and cfunction accepted and treated argument types in the same way.

For example, consider the following method to pass a re-entrant callback routine to the GNU libc qsort_r function. (Warning: don't try this with MacOS or BSD, where qsort_r has a different argument order in its callback.)

function qsort_r_callback{T}(a::Ptr{T}, b::Ptr{T}, f::Function)
    int32(f(unsafe_ref(a), unsafe_ref(b)) ?
          -1 : unsafe_ref(a) == unsafe_ref(b) ? 0 : +1)
end

function qsort_r{T}(A::Vector{T}, f::Function)
    ccall(:qsort_r, Void, (Ptr{T}, Uint, Uint, Ptr{Void}, Any),
          A, length(A), sizeof(T),
          cfunction(qsort_r_callback, Cint, (Ptr{T}, Ptr{T}, Function)),
          f)
    A
end

This works great, even for anonymous functions, e.g. qsort_r([17,2,7,3,-1,14], (a,b) -> a < b). However, if you change the Any argument of ccall to the sensible-seeming Function type, it segfaults.

@vtjnash
Copy link
Member

vtjnash commented Mar 13, 2013

Jeff and I agree that this is actually a mistake in the implementation of cfunction and it needs to be modified to act like ccall in this case. So the function parameter should be declared to take type Any (or Ptr{Void}). A type assertion can be used in the body of the function if desired to convert from Any (or unsafe_pointer_to_objref())

Some background: ccall defines that a the name of a type means you are passing the struct of that type by-value (although it doesn't work right now for most types). If you want a pointer to a struct, then you must pass a Ptr{Type}. Finally, if you want a jl_value_t*, then you must use Any.

@vtjnash
Copy link
Member

vtjnash commented Mar 7, 2015

cfunction will be significantly altered when #7906 merges (soon)

@JeffBezanson
Copy link
Member

@vtjnash is this fixed now?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking This change will break code
Projects
None yet
Development

No branches or pull requests

5 participants