IronPython3宿主继承.NET类时抛出TypeErrorException元类冲突问题
问题:IronPython继承C#类型时触发元类冲突错误
定义的C#类型
[PythonType] public class ScriptBase { public virtual int TestMe() { return 11; } }
IronPython继承代码
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
C#引擎初始化与类型注册代码
// 测试执行代码 ScriptEngine _engine = Python.CreateEngine(); // 创建基础模块 ScriptScope _gameScope = _engine.CreateModule("Base"); // 在模块中暴露ScriptBase类 _gameScope.SetVariable(nameof(ScriptBase), typeof(ScriptBase)); // 通过包装器从文件流加载源码并编译 ScriptSource source = engine.CreateScriptSource(new CodeProvider(inStream), package, Encoding.ASCII, SourceCodeKind.Statements); CompiledCode compiled = source.Compile(); // 为继承类创建新模块 _scope = engine.CreateModule(package); // 执行代码——此行抛出异常 compiled.Execute(_scope);
补充信息
- 已尝试导入CLR、定义
__init__和__new__,均无效 - 使用
.CreateModule可正常实例化和管理现有类型,仅继承操作出错 - 运行环境: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)
解决方案
错误核心原因:直接将C#的Type对象暴露给IronPython,未经过IronPython的类型包装,导致原生CLR类型的元类与IronPython类的元类不兼容,无法满足继承的元类规则。
修复方式一:包装C#类型后再注册
修改C#中注册类型的代码,用IronPython的ClrModule.GetPythonType方法将原生C#类型包装为IronPython可识别的继承类型:
// 替换原来的SetVariable行 var wrappedType = IronPython.Runtime.ClrModule.GetPythonType(_engine, typeof(ScriptBase)); _gameScope.SetVariable(nameof(ScriptBase), wrappedType);
修复方式二:在Python脚本中直接导入CLR类型
如果允许,可通过IronPython的clr模块直接导入C#程序集,无需手动注册类型,IronPython会自动处理包装:
import clr clr.AddReference("你的C#程序集名称") from 你的命名空间 import ScriptBase class TestClass(ScriptBase): pass
原理说明
直接传递typeof(ScriptBase)时,IronPython仅将其视为外部CLR类型,而非可继承的Python类型。经过GetPythonType包装后的类型会携带IronPython类的元类,才能让Python子类正确继承。
内容的提问来源于stack exchange,提问作者noisy cat
相关产品推荐
相关产品推荐

