如何将Python回调传递给C#函数调用
我正在尝试在Ubuntu上使用Mono,通过python.net来调用C#的类。
到目前为止,我已经成功地用一个参数调用了一个简单的函数。现在我想做的是把一个Python的回调函数传递给C#的函数。
我尝试了下面的几种方法,但都没有成功。有没有人能教我怎么做到这一点?
// C# - testlib.cs
class MC {
public double method1(int n) {
Console.WriteLine("Executing method1" );
/* .. */
}
public double method2(Delegate f) {
Console.WriteLine("Executing method2" );
/* ... do f() at some point ... */
/* also tried f.DynamicInvoke() */
Console.WriteLine("Done executing method2" );
}
}
Python脚本
import testlib, System
mc = testlib.MC()
mc.method1(10) # that works
def f():
print "Executing f"
mc.method2(f)
# does not know of method2 with that signature, fair enough...
# is this the right way to turn it into a callback?
f2 = System.AssemblyLoad(f)
# no error message, but f does not seem to be invoked
mc.method2(f2)
2 个回答
2
看起来你应该明确地定义你的委托:
class MC {
// Define a delegate type
public delegate void Callback();
public double method2(Callback f) {
Console.WriteLine("Executing method2" );
/* ... do f() at some point ... */
/* also tried f.DynamicInvoke() */
Console.WriteLine("Done executing method2" );
}
}
然后在Python代码中(这是根据文档的粗略猜测):
def f():
print "Executing f"
# instantiate a delegate
f2 = testlib.MC.Callback(f)
# use it
mc.method2(f2)
7
试着传递 Action
或 Func
,而不是直接用原始函数:
我在这里使用了 IronPython(因为我现在在任何机器上都没有安装 mono,但根据 Python.NET 的 文档,我觉得应该可以工作。实际上你的代码差不多可以,但你需要根据需要导入 Action
或 Func
委托。
Python 代码:
import clr
from types import *
from System import Action
clr.AddReferenceToFileAndPath(r"YourPath\TestLib.dll")
import TestLib
print("Hello")
mc = TestLib.MC()
print(mc.method1(10))
def f(fakeparam):
print "exec f"
mc.method2(Action[int](f))
这是控制台输出:
Hello
Executing method1
42.0
Executing method2
exec f
Done executing method2
C# 代码:
using System;
namespace TestLib
{
public class MC
{
public double method1(int n)
{
Console.WriteLine("Executing method1");
return 42.0;
/* .. */
}
public double method2(Delegate f)
{
Console.WriteLine("Executing method2");
object[] paramToPass = new object[1];
paramToPass[0] = new int();
f.DynamicInvoke(paramToPass);
Console.WriteLine("Done executing method2");
return 24.0;
}
}
}
我再次查看了 Python.net 的文档,特别是 使用泛型 部分,还发现了这个 Python.NET 泛型类型的命名和解析,看起来你需要明确指定参数类型。
一个(反射的)泛型类型定义(如果存在一个具有给定基本名称的泛型类型定义,并且没有与该名称相同的非泛型类型)。这个泛型类型定义可以使用 [] 语法绑定到一个封闭的泛型类型。尝试使用 () 实例化一个泛型类型定义会引发类型错误。