Hi, does anyone managed to call a Python lambda function from inside a C# component?
I already confirmed a C# lambda function wrapped by a Func<> can be simply called from within a Python environment, but cannot find the way to do the other way around.
The senario is like this.
I have a code written in Python but it turns out I need to salvage all of them to a C# node.
However there is a function too complicated and I don’t want to rewrite it. So I’m thinking to rewrite the main code in C# but call a function coded in a Python node from within a C# node.
Thanks!
Haven’t tried it before, but it looks doable writing a wrapper for the python class.
You can execute a python script with the console in C# and then retrieve the result to the component, using the process class, but you have to format the result because console only return strings. I wouldn’t use IronPython.
System.Diagnostics.Process proc = new System.Diagnostics.Process
{
StartInfo = new System.Diagnostics.ProcessStartInfo
{
FileName = @"C:\windows\system32\cmd.exe",
Arguments = @"/c C:\Users\python.exe C:\Users\xxxx.py ",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
}
};
proc.Start();
string result = proc.StandardOutput.ReadToEnd();
RunPython.gh (2.5 KB)
Hi, sorry my explanation was not clear enough.
What I’m trying to do is to pull out a lambda function (can be a regular function as well) from a Python node and catch it by a C# node and execute the function.
The general discussion of running a Python code from inside a C# code is too tricky. I’m taking advantage from the fact that, in GH environment, you can directly connect Python and C# nodes and pass some objects, and since those objects are .NET objects, there should be a way.
Python node
a=lambda x:x*2
Output:a
C# node
Print(F(10d))
Input F (connected to “a” of the Python node)
Amazingly the below works without any tick(calling a C# function from inside a Python node)
C# node
A=new Func<double,double>((x)=>x*2);
Output:A
python node
print f(10.0)
Input f (connected to the “A” of the C# node)
Also, sorry for the confusion, this guys is the same person as the first post. I couldn’t find a way to change the account and I have to PCs tied to different accounts.
In the first image, A is a function. You are therefore passing the function with the lambda in it to the python.
In the second image, you are declaring a as the result of the lambda function as compared to being the function.
You can do something similar by declaring the variable a as a function:
But I’m not really sure how to get the function to be called.
Only way I think this might work is:
https://documentation.help/IronPython/getting_started.html
where engine.createscriptsource (CodeObject content) is used to set the function as the code.
I can’t confirm as I’m not familiar with the c# code component in grasshopper.
Otherwise it would be easier to just wrap the function as a class in python and pass the class to the c#.
You then set all the arguements in C# and then call the function to run on that class and get the result back out.
Hello, I believe
a=lambda x:x*2
and
def func(x):
return x*2
a=func
are the same.)
The problem is that C# is a static typing language. So you need to figure out what class is actually wrapping those functions internally in Python, and declare the class types accurately in C#, which I think is too much pain and headache. The reason the other way around was possible is that Python is a dynamic typing language.
Actually I found a solution online. It seems like it is possible to wrap a function by C# Func<> or Action<>.
import clr
from System import Func
import System
import System.Collections.Generic
def f(x):
return x*2
a=Func[System.Double,System.Double](f)
this a can be passed to a C# node, then cast to Func<double,double> safely, and finally can be called simply by F(x);
Yey! Thanks for the help!
1 Like
I don’t use lambda notation in python, so didn’t know that.
Glad your problem is solved though.