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

automatic return type conversion / assertion for cfunction? #6285

Closed
StefanKarpinski opened this issue Mar 27, 2014 · 6 comments
Closed

automatic return type conversion / assertion for cfunction? #6285

StefanKarpinski opened this issue Mar 27, 2014 · 6 comments

Comments

@StefanKarpinski
Copy link
Member

This is kind of an annoyance:

julia> foo(msg::Ptr{Uint8}) = println(bytestring(msg))
foo (generic function with 1 method)

julia> cfunction(foo, None, (Ptr{Uint8},))
ERROR: cfunction: return type of foo does not match
 in cfunction at c.jl:23

julia> foo(msg::Ptr{Uint8}) = println(bytestring(msg))::Nothing
foo (generic function with 1 method)

julia> cfunction(foo, None, (Ptr{Uint8},))
Ptr{Void} @0x0000000108ae10b0

julia> ccall(ans, None, (Ptr{Uint8},), pointer("hello"))
hello

Would it make sense to either insert an implicit call to convert on the return value or a type assertion? After all, you are telling cfunction the exact type that must be returned already.

@JeffBezanson
Copy link
Member

We don't want to compile a new function body for every call to cfunction. But if the cfunctions don't have to match what we've compiled already, we would need to store an additional table of function bodies.

Void might be a special case though, and we could just allow it regardless of what the function actually returns. I believe this would work with cdecl at least.

@StefanKarpinski
Copy link
Member Author

In general, I've found that my pattern when using cfunction is to define a Julia function that has a C-like signature and then call cfunction with the exact same signature, which feels awfully redundant. Are there use cases where the same Julia function is passed to cfunction different ways? I'm having a hard time imagining this not being a one-to-one mapping.

@JeffBezanson
Copy link
Member

See #2554. It's not that simple, mostly because of passing structs by value vs. by reference. For some functions with a single definition, we could indeed skip the argument types in cfunction, but we should probably still require the return type since if the inferred type is not what you expect very bad things would happen mysteriously.

@StefanKarpinski
Copy link
Member Author

Ok, feel free to close if you think this isn't feasible.

@JeffBezanson
Copy link
Member

Actually this reminds me of a key feature we should have, which is the ability to declare the equivalent of extern "C" on a julia function. I'm pretty sure @loladiro brought this up at some point. This would basically cause generation of an un-mangled name for a C-callable version of a function. Then you could use cglobal(:julia_foo) instead of cfunction, which could help remove some redundancy.

This should be pretty easy to implement; I'm just not sure what the syntax should be.

@StefanKarpinski
Copy link
Member Author

Does that mean that when it is compiled it would be checked to be cfunctionable? A macro? I.e.:

@ccallable foo(msg::Ptr{Uint8}) = println(bytestring(msg))

Or maybe @extern, but I think that's a little less obvious, honestly. The alternative would be a keyword, but I'm not sure we want to go adding keywords endlessly.

JeffBezanson added a commit that referenced this issue Apr 3, 2014
…function

ref #6285

ccallable(func, [ret_type], arg_type, [name])

is similar to cfunction(), but adds an alias "name" to the global
symbol table exported from sys.so (defaults to the function name).

a method definition can also be prefixed with `@ccallable`

also:
- load sys.so with RTLD_GLOBAL
- shorten jlcall wrapper names to jlcall_f instead of jlcall_julia_f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants