I would like to change it so that it will return a function that takes Cint and returns Cint, in order to pass it to C code as a callback using ccall. I expected this to work, but it doesn’t. (It gives a syntax error, unless I remove the type assertion on the parameter x.)
function make_func()
f = function(x::Cint)::Cint
return x*10
end
return f
end
Is there a way that I can specify both the input and return types of an anonymous function?
Edit: I misread the question. The post below is probably not very helpful, sorry.
Original post:
You don’t actually need to restrict the anonymous function at all. Instead, you should use @cfunction to generate the C-compatible function pointer:
julia> function make_func()
x -> x * 10
end
make_func (generic function with 1 method)
julia> @cfunction(make_func, Cint, (Cint,))
Ptr{Nothing} @0x00007f14ade9a230
I’m having a hard time making sense of that. I don’t want to turn make_func into a cfunction, I want to turn the function returned by make_func into a cfunction, i.e.
I note also that I can get around this by doing the following:
func = make_func()
# this function exists only to control the type of func()
function func_wrapper(x::Cint)::Cint
return func(x)
end
func_wrapper_c = @cfunction($func_wrapper, Cint, (Cint,))
This appears to work correctly, and to behave as a C function of type int (*f)(int), as expected. But it’s weird and hacky to have to create the func_wrapper function just to control the type of the anonymous function. I’m asking how to do that in a more paradigmatic way.
Looks like the anonymous function form is bugged in how it parses the return type assertions — it puts them on the argument instead! Tracked as issue #32557:
As a workaround, you can just use a named function instead — it’s still scoped inside your function and forms a closure if you capture any variables. Or you can just manually convert things to Cint yourself when you return — the function return declaration is just a handy way to annotate that.
Great, many thanks. Thanks for the tip about named functions! So here is working code that does what I wanted:
function make_func()
function f(x::Cint)::Cint
x*10
end
return f
end
function main()
func = make_func()
func_wrapper_c = @cfunction($func, Cint, (Cint,))
result = ccall((:myTestFunction, "myTestLib"), Int32, (Ptr{Cvoid},), func_wrapper_c)
println(result)
end
main()