-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Description
--- update ---
the original issue is pretty much covered by cfunction. the remaining issues are:
- support closures
- adding conversion wrapper in case of inexact matches
---- original text ---
To enable certain function calls to C code, it would be helpful to have a function callback API in Julia (this is partly inspired by the libuv interface, which ended up handling most of these issues by creating a tight coupling between julila function and types and libuv callbacks and types)
The two issues that I currently see would need to be handled are:
- Since pointers are leaving control of Julia, the garbage collector needs to know not to clean-up anything that may be used in the future (and notified when it can)
- Since C doesn't natively have type information, it requires some sort of reverse ccall interface
To handle 1, I think it may be safest to create a garbage collector allocation pool. Objects can be pushed to and popped from it from within Julia (using ref counting?). Then possibly add a default behavior that parameters to a ccall containing a Callback object are automatically saved until all callbacks are manually deleted. (since additional and previous calls to C functions may also hold onto object pointers, it may be useful to have this as a separately available function)
To handle 2, it will be necessary to indicate type information to the ccall. One possibility is to make a type that contains the information type Callback{ params <: Tuple } end and is passed to the ccall in the third argument tuple. A generic function name would then be passed in the parameters list. A second possibility is to make Callback a simple type that contains all of that information type Callback; params <: Tuple; f :: Function; end. A third (similar) possibility is to do the exact function lookup in Julia and require something like the value returned by getmethods and printed by whicht. In any case, I envision that ccall would JIT an intermediary function that converts from raw bits types to Julia types. This prompts the last possibility (and possibly my favorite) of having make_callback return a raw pointer to a newly JIT'd intermediary C function:
callback_fcn = make_callback(fcn::Function, arg_types::Tuple)
arg2 = "test"
cpreserve(arg2); cpreserve(fcn) # if args are not automatically preserved
ccall(:cfcn, Void, (Ptr, String), callback_fcn, arg2)
...
crelease(arg2) # if args are not automatically preserved
crelease(fcn) # if args are automatically preserved, arg2 won't be freed till after this point
A final question is whether pointer_to_array is the best way to grab a c array? Or is there some way to indicate this in the argument type?
Thoughts and alternatives? Am I missing any challenging callback argument types?