Python NET call C# method which has a return value and an out parameter
Asked Answered
B

1

6

I'm having the following static C# method

public static bool TryParse (string s, out double result)

which I would like to call from Python using the Python NET package.

import clr
from System import Double
r0 = Double.IsNaN(12.3) # works

r1, d1 = Double.TryParse("12.3") # fails! TypeError: No method matches given arguments. This works in IronPython.

d2 = 0.0
r2, d2 = Double.TryParse("12.3", d2) # fails! TypeError: No method matches given arguments

Any idea?

Update

I found the following answer, see https://mcmap.net/q/1772626/-how-to-use-a-net-method-which-modifies-in-place-in-python.

CPython using PythonNet does basically the same thing. The easy way to do out parameters is to not pass them and accept them as extra return values, and for ref parameters to pass the input values as arguments and accept the output values as extra return values.

This would claim that r1, d1 = Double.TryParse("12.3") should work, but it doesn't.

Bugloss answered 14/2, 2019 at 14:4 Comment(0)
T
10

I had to address a similar problem recently with using Python for .NET, let me share with you what I have found out.

You need to pass as many arguments as the method requires to. Since the concept of out arguments (= passed by refence) doesn't apply to Python, the trick is to pass some dummy arguments of the expected type.

The method call is going to return first the values that it is supposed to return, and the out values.

For my use case, the C# method I was calling did not return anything originally (void method), yet, the Python call returned first None and then the out values I was after, which is the expected behaviour as stated here.

Your first attempt could not work because you pass only one argument, while the method expects two, be they out or ref arguments.

r1, d1 = Double.TryParse("12.3")

Your second attempt could not work either because the type of the dummy argument does not match with the type expected by the method, in that case Double.

d2 = 0.0
r2, d2 = Double.TryParse("12.3", d)

This will do the trick:

import clr
from System import Double
dummy_out = Double(0.)
returned_val, real_out = Double.TryParse("12.3", dummy_out)

You can observe that this last line does not have any effect on dummy_out by checking its id before and after the call.

Hence, a shorter version of the code you need would be:

returned_val, real_out = Double.TryParse("12.3", Double(0.))
Tillett answered 18/2, 2019 at 13:40 Comment(2)
Thanks for your answer. My second attempt was r2, d2 = Double.TryParse("12.3", d2), so d2 is defined. I'll edit my question. Sorry my fault. I still get the the following error: TypeError: No method matches given arguments.Bugloss
I tried to get your code working. It does work if you follow what I wrote, but there was one thing I did not get correctly, which is that the types of the dummy out arguments must be the same as the ones the method expects. This works returned_val, real_out = Double.TryParse("12.3", Double(0.))Tillett

© 2022 - 2024 — McMap. All rights reserved.