yglukhov / nimpy

Nim - Python bridge
MIT License
1.47k stars 61 forks source link

Passing python function to Nim proc gives unknownTypeCompileError() #89

Closed HugoGranstrom closed 5 years ago

HugoGranstrom commented 5 years ago

Hi, To start with I was happily surprised how easy it was to write python modules using Nimpy, good job. Looking forward to where this will end up ;-)

Using:

I'm trying to make a python module with Nimpy and I want to take a Python function as a parameter in my Nim proc but I'm getting an error trying to compile it:

nimath.nim(7, 65) template/generic instantiation from here .......nimble\pkgs\nimpy-0.1.0\nimpy.nim(689, 15) template/generic instantiation from here .......nimble\pkgs\nimpy-0.1.0\nimpy.nim(400, 32) Error: type mismatch: got <proc (x: float64): float64{.closure.}> but expected one of: proc unknownTypeCompileError() expression: unknownTypeCompileError(v)

The code I tried to compile was this: proc euler(f: proc (x: float64): float64, x0: float64): float64 {.exportpy.} = return f(x0)

I tried compiling it without the {.exportpy.} pragma and it worked fine: proc euler(f: proc (x: float64): float64, x0: float64): float64 = return f(x0)

proc f(x: float64): float64 = return x * 2

echo euler(f, 2) # prints 4.0 as expected Is this supported yet or is it me who's just being blind?

Thank you in advance :-D

yglukhov commented 5 years ago

Ugh. Thats not supported indeed. But you should be able to call PyObjects, iirc.

HugoGranstrom commented 5 years ago

Thanks for the reply :-) How would you suggest I try to solve this? Is it even possible? Should I take a PyObject as an input and then call it somehow?

yglukhov commented 5 years ago

Just pushed something that should help. So now it's like:

proc euler(f: PyObject, x0: float64): float64 {.exportpy.} = f.callObject(x0).to(float64)

Proper "function passing" is coming "soon".

yglukhov commented 5 years ago

Ok, your originally suggested approach is now supported.

HugoGranstrom commented 5 years ago

Wow that was fast :-D The PyObject approach is working as expected but I can't get the tests to compile for the other approach:

nimfrompy.nim(110, 45) template/generic instantiation from here
..\nimpy.nim(743, 19) template/generic instantiation from here
..\nimpy.nim(402, 20) template/generic instantiation from here
..\nimpy.nim(967, 29) Error: 'result' is of type <NimNode> which cannot be captured as it would violate memory safety, declared here: ..\nimpy.nim(954, 0)
stack trace: (most recent call last)
C:\Users\User\code\nim\gitrepos\nimpy\nimpy.nimble(19) testTask
C:\Users\User\nim-0.19.4\lib\system\nimscript.nim(237) exec
C:\Users\User\nim-0.19.4\lib\system\nimscript.nim(237, 7) Error: unhandled exception: FAILED: nim c --app:lib --out:tests\nimfrompy.pyd tests\nimfrompy.nim
yglukhov commented 5 years ago

Fixed

HugoGranstrom commented 5 years ago

Thank you once again, now it works like a charm!

Have a great day :-)