【发布时间】:2018-04-09 15:27:47
【问题描述】:
我得到了一个用 C# 编写的库,我正在尝试使用 Python for .NET 调用它。
我需要一个实例的主类有一个构造函数,例如:
GDhuClient(IGDhuSettings)
没有(公开的)类实现IGDhuSettings 接口。当我创建一个 Python 类来实现它时,例如,
class PyGDhuSettings(IGDhuSettings):
...
如果我没有__new__ 方法或者如果我以正常方式定义一个方法,我会得到TypeError: interface takes exactly one argument:
def __new__(cls):
return super().__new__(cls)
如果我尝试将接口实例化为一个类,我会得到相同的错误(没有或 >1 个参数)或<whatever> does not implement IGDhuSettings 如果我传递一个参数。
using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace Python.Runtime
{
/// <summary>
/// Provides the implementation for reflected interface types. Managed
/// interfaces are represented in Python by actual Python type objects.
/// Each of those type objects is associated with an instance of this
/// class, which provides the implementation for the Python type.
/// </summary>
internal class InterfaceObject : ClassBase
{
internal ConstructorInfo ctor;
internal InterfaceObject(Type tp) : base(tp)
{
var coclass = (CoClassAttribute)Attribute.GetCustomAttribute(tp, cc_attr);
if (coclass != null)
{
ctor = coclass.CoClass.GetConstructor(Type.EmptyTypes);
}
}
private static Type cc_attr;
static InterfaceObject()
{
cc_attr = typeof(CoClassAttribute);
}
/// <summary>
/// Implements __new__ for reflected interface types.
/// </summary>
public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
{
var self = (InterfaceObject)GetManagedObject(tp);
int nargs = Runtime.PyTuple_Size(args);
Type type = self.type;
object obj;
if (nargs == 1)
{
IntPtr inst = Runtime.PyTuple_GetItem(args, 0);
var co = GetManagedObject(inst) as CLRObject;
if (co == null || !type.IsInstanceOfType(co.inst))
{
Exceptions.SetError(Exceptions.TypeError, $"object does not implement {type.Name}");
return IntPtr.Zero;
}
obj = co.inst;
}
else if (nargs == 0 && self.ctor != null)
{
obj = self.ctor.Invoke(null);
if (obj == null || !type.IsInstanceOfType(obj))
{
Exceptions.SetError(Exceptions.TypeError, "CoClass default constructor failed");
return IntPtr.Zero;
}
}
else
{
Exceptions.SetError(Exceptions.TypeError, "interface takes exactly one argument");
return IntPtr.Zero;
}
return CLRObject.GetInstHandle(obj, self.pyHandle);
}
}
}
如果没有 CoClass(没有定义)或已经有一个实现它的类,我看不到一种在 Python 中实现 C# 接口的方法。
我在这里遗漏了一些细微差别,还是这是 Python for .NET 的限制?
在 GitHub 上讨论:https://github.com/pythonnet/pythonnet/issues/674
【问题讨论】:
-
我没有将 Python for .NET 用于任何严重的事情,但我可以看出这可能是一个故意的限制。您的 Python 代码不在 .NET 中运行,因此它必须为接口的每个方法构建一个代理方法,这可能很慢而且很脆弱,所以他们可能希望您修改您的设计,这样您就可以通过一个委托,还是改用 IronPython?
标签: c# python interface python.net pythonnet