IronPython3主机抛出“类型错误异常:从.net类继承时发生”元类冲突

xytpbqjk  于 2023-03-13  发布在  .NET
关注(0)|答案(1)|浏览(128)

我有以下C#类型:

[PythonType]
public class ScriptBase
{
    public virtual int TestMe()
    {
        return 11;
    }
}

然后,我尝试在python中创建一个继承自ScriptBase的类:

from Base import ScriptBase

class TestClass (ScriptBase):
    pass

尝试执行此脚本将生成:TypeErrorException: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
下面是我创建引擎和注册类型的过程:

// Executed to test
ScriptEngine _engine = Python.CreateEngine();

// Create base module
ScriptScope _gameScope = _engine.CreateModule("Base");

// Expose ScriptBase class in the module
_gameScope.SetVariable(nameof(ScriptBase), typeof(ScriptBase));

// Load the source from a file stream through a wrapper and compile
ScriptSource source = engine.CreateScriptSource(new CodeProvider(inStream), package, Encoding.ASCII, SourceCodeKind.Statements);
CompiledCode compiled = source.Compile();

// Create new module for the inheriting classes
_scope = engine.CreateModule(package);

// Execute the code -- this line throws an exception
compiled.Execute(_scope);

我试过导入CLR并定义__init____new__,但没有什么变化。.CreateModule方法适用于示例化和管理现有类型,只是继承部分似乎被破坏了--我遗漏了什么步骤吗?
我不是很精通python,所以我不知道这条消息抱怨什么,我已经尝试了很多在线方法,但似乎总是在同一个地方结束。
运行时是mono,目标是.Net 4.x。下面是完整的调用堆栈。

TypeErrorException: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
IronPython.Runtime.Types.PythonType.FindMetaClass (IronPython.Runtime.Types.PythonType cls, IronPython.Runtime.PythonTuple bases) (at <57a5bd653356491bba8a61ecf9211193>:0)
IronPython.Runtime.Operations.PythonOps.MakeClass (IronPython.Runtime.FunctionCode funcCode, System.Func`2[T,TResult] body, IronPython.Runtime.CodeContext parentContext, System.String name, IronPython.Runtime.PythonTuple bases, IronPython.Runtime.PythonDictionary keywords, System.String selfNames) (at <57a5bd653356491bba8a61ecf9211193>:0)
Microsoft.Scripting.Interpreter.FuncCallInstruction`8[T0,T1,T2,T3,T4,T5,T6,TRet].Run (Microsoft.Scripting.Interpreter.InterpretedFrame frame) (at <9784853821ea47dbb6bb1f3e03091049>:0)
Microsoft.Scripting.Interpreter.Interpreter.Run (Microsoft.Scripting.Interpreter.InterpretedFrame frame) (at <9784853821ea47dbb6bb1f3e03091049>:0)
Microsoft.Scripting.Interpreter.LightLambda.Run2[T0,T1,TRet] (T0 arg0, T1 arg1) (at <9784853821ea47dbb6bb1f3e03091049>:0)
IronPython.Compiler.PythonScriptCode.RunWorker (IronPython.Runtime.CodeContext ctx) (at <57a5bd653356491bba8a61ecf9211193>:0)
IronPython.Compiler.PythonScriptCode.Run (Microsoft.Scripting.Runtime.Scope scope) (at <57a5bd653356491bba8a61ecf9211193>:0)
IronPython.Compiler.RuntimeScriptCode.InvokeTarget (Microsoft.Scripting.Runtime.Scope scope) (at <57a5bd653356491bba8a61ecf9211193>:0)
IronPython.Compiler.RuntimeScriptCode.Run (Microsoft.Scripting.Runtime.Scope scope) (at <57a5bd653356491bba8a61ecf9211193>:0)
Microsoft.Scripting.Hosting.CompiledCode.Execute (Microsoft.Scripting.Hosting.ScriptScope scope) (at <0d164baeace648b2930cfd25249cf9f3>:0)
(wrapper remoting-invoke-with-check) Microsoft.Scripting.Hosting.CompiledCode.Execute(Microsoft.Scripting.Hosting.ScriptScope)
wkyowqbh

wkyowqbh1#

在浏览了IronPython源代码之后,我已经设法自己找到了解决方案(感谢开源软件的好人,感谢你们的工作)。
事实证明,正确地将.net Type暴露给IronPython世界是通过DynamicHelpers.GetPythonTypeFromType(System.Type)的,我目前正在使用这个扩展方法在ScriptScope中注册我的类型:

public static void RegisterType(this ScriptScope self, Type t) =>
    self.SetVariable(t.Name, DynamicHelpers.GetPythonTypeFromType(t));

希望这能帮到什么人。

相关问题