Is there a good way of passing a closure as a callback in a C API?
The API accepts a function pointer and a user data pointer. The API can be made to call the function with the user-data as its first argument. I see that in the generated C code, Nim passes the closure environment as the first parameter. So I figure that the most efficient approach would be to simple split the closure into its function pointer and environment pointer, and pass those two directly to the C API. But that also seems quite hacky.
I suppose the other approach is to pass the whole closure pointer as user-data, then pass a proxy procedure as the callback function, and have the proxy procedure call the closure.
Any opinions?
Thanks. Okay, so now my problem is that when I create a nested proc, Nim seems to ignore pragmas. So it always generates a nimcall/fastcall calling convention, although I'm trying to get it to not. Is that a bug?
I thought Nim passed the closure as the first argument, but I now see that it's actually the last argument (don't know why I saw otherwise first). Is that always the case?
Is that a bug?
If the compiler disagrees on what the calling convention should be, it should report an error, not silently ignore your request. So yes, that's a bug.
Is that always the case?
Yes.
Okay, I don't think I can use rawProc, rawEnv in my case. Because I can't guarantee that I will get the environment to the proc as the last argument.
I am trying out this approach now:
proc myClosure(i: int) =
...
proc myProxy(c: ref type(inner), i: int) =
c[](i)
var p = new(type(myClosure))
p[] = myClosure
Then pass p and myProxy to the C API.
Edit: I should mention that the behavior of closures as values confused me for quite a bit, until I realized that they seem to be treated like tuples.
Hi Skyfex,
can you give more details on how you have solved this problem?