C# “如何发布模块”__主要的;在托管IronPython 2.0时?

C# “如何发布模块”__主要的;在托管IronPython 2.0时?,c#,hosting,ironpython,C#,Hosting,Ironpython,我正在尝试将[rlcompleter][1]功能添加到我的in分支中 但是,我在线路上遇到了一个难题: import __main__ 在rlcompleter.py中。这是因为我没有这样的模块。我一直在搜索/筛选IronPython2.0代码库,试图找出如何发布模块 似乎我可以从IronPython.Runtime.PythonContext的实例中使用PublishModule(字符串名称,PythonModule模块)方法来实现这一点。但我在以下方面遇到了问题: 获取PythonCon

我正在尝试将
[rlcompleter][1]
功能添加到我的in分支中

但是,我在线路上遇到了一个难题:

import __main__
rlcompleter.py
中。这是因为我没有这样的模块。我一直在搜索/筛选IronPython2.0代码库,试图找出如何发布模块

似乎我可以从
IronPython.Runtime.PythonContext
的实例中使用
PublishModule(字符串名称,PythonModule模块)
方法来实现这一点。但我在以下方面遇到了问题:

  • 获取
    PythonContext
    实例
  • 获取
    PythonModule
    实例
我拥有的是一个
ScriptEngine
和一个
ScriptScope
。我希望将范围发布为模块
\uuuu main\uuuu
。据我所知,范围已经附加到模块,但我不知道如何访问它

下面是我想将其结合在一起的代码要点:

    /// <summary>
    /// Set up an IronPython environment - for interactive shell or for canned scripts
    /// </summary>
    public void SetupEnvironment(ScriptEngine engine, ScriptScope scope)
    {                        
        // add variables from Revit
        scope.SetVariable("__revit__", _commandData.Application);
        scope.SetVariable("__commandData__", _commandData);
        scope.SetVariable("__message__", _message);
        scope.SetVariable("__elements__", _elements);
        scope.SetVariable("__result__", (int)Result.Succeeded);                        

        // add preconfigures variables
        scope.SetVariable("__vars__", RevitPythonShellApplication.GetVariables());

        /* register scope as __main__ module here?! */         

        // add the search paths
        AddSearchPaths(engine);
    }
//
///设置IronPython环境-用于交互式shell或罐装脚本
/// 
公共void设置环境(ScriptEngine引擎、ScriptScope范围)
{                        
//从Revit添加变量
scope.SetVariable(“\uuuu revit\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
scope.SetVariable(“\uuuuCommandData\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
scope.SetVariable(“\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
scope.SetVariable(“\uuuu元素”、\u元素);
SetVariable(“\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
//添加预配置变量
scope.SetVariable(“\uuuu vars\uuuuuuu”,RevitPythonShellApplication.GetVariables());
/*在此处将作用域注册为_u主_;模块?!*/
//添加搜索路径
添加搜索路径(引擎);
}

没关系,我仔细阅读了IronPython 2.0.3源代码,得出了以下结论:

  • PythonContext
    是一个
    Microsoft.Scripting.Runtime.LanguageContext
  • ScriptEngine
    的语言上下文可以通过
    Microsoft.Scripting.Hosting.Providers.HostingHelpers.GetLanguageContext(ScriptEngine)
    方法获得
  • 如果您有一个用于python的
    ScriptEngine
    ,那么您就可以强制转换
哇。现在我终于有了我的
PythonContext
!所以我要打电话给
CreateModule
PublishModule
,在喝茶之前回家

等等。否。首先,
CreateModule
的第二个参数是
Microsoft.Scripting.Runtime.Scope
。我们只有一个
Microsoft.Scripting.Hosting.ScriptScope
。它恰好包含一个
范围
,但其访问器是
内部
。所以我们需要先做一些反思

下面是我提出的解决方案补充的示例代码:

/// <summary>
/// Set up an IronPython environment - for interactive shell or for canned scripts
/// </summary>
public void SetupEnvironment(ScriptEngine engine, ScriptScope scriptScope)
{
    // add variables from Revit
    scriptScope.SetVariable("__revit__", _commandData.Application);
    scriptScope.SetVariable("__commandData__", _commandData);
    scriptScope.SetVariable("__message__", _message);
    scriptScope.SetVariable("__elements__", _elements);
    scriptScope.SetVariable("__result__", (int)Result.Succeeded);           

    // add preconfigures variables
    scriptScope.SetVariable("__vars__", RevitPythonShellApplication.GetVariables());

    // add the current scope as module '__main__'
    var languageContext = Microsoft.Scripting.Hosting.Providers.HostingHelpers.GetLanguageContext(engine);
    var pythonContext = (IronPython.Runtime.PythonContext)languageContext;
    var module = pythonContext.CreateModule(null, GetScope(scriptScope), null, IronPython.Runtime.ModuleOptions.None);            
    pythonContext.PublishModule("__main__", module);

    // add the search paths
    AddSearchPaths(engine);
}

/// <summary>
/// Be nasty and reach into the ScriptScope to get at its private '_scope' member,
/// since the accessor 'ScriptScope.Scope' was defined 'internal'.
/// </summary>
private Microsoft.Scripting.Runtime.Scope GetScope(ScriptScope scriptScope)
{
    var field = scriptScope.GetType().GetField(
        "_scope", 
        System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    return (Microsoft.Scripting.Runtime.Scope) field.GetValue(scriptScope);
}
//
///设置IronPython环境-用于交互式shell或罐装脚本
/// 
公共void设置环境(ScriptEngine引擎、ScriptScope ScriptScope)
{
//从Revit添加变量
SetVariable(“\uuuu revit\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
SetVariable(“\uuuuCommandData\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
SetVariable(“\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
SetVariable(“\uuuu元素”、\u元素);
SetVariable(“\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
//添加预配置变量
SetVariable(“_变量”,RevitPythonShellApplication.GetVariables());
//将当前作用域添加为模块“\uuuu main\uuuuu”
var languageContext=Microsoft.Scripting.Hosting.Providers.HostingHelpers.GetLanguageContext(引擎);
var pythonContext=(IronPython.Runtime.pythonContext)languageContext;
var module=pythonContext.CreateModule(null,GetScope(scriptScope),null,IronPython.Runtime.ModuleOptions.None);
pythonContext.PublishModule(“\uuuuu main\uuuuuuuuuuuuuuuuuuuuuuuuuuuu”,模块);
//添加搜索路径
添加搜索路径(引擎);
}
/// 
///下流,进入ScriptScope获取其私有的“\u scope”成员,
///因为访问器“ScriptScope.Scope”定义为“内部”。
/// 
私有Microsoft.Scripting.Runtime.Scope GetScope(ScriptScope ScriptScope)
{
var field=scriptScope.GetType().GetField(
“_范围”,
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
返回(Microsoft.Scripting.Runtime.Scope)字段.GetValue(scriptScope);
}

我故意保留类型中的所有名称空间。我发现IronPython代码有点难以理解,并且经常对在何处定义感到困惑。

我遇到了同样的问题。我试图使用ScriptEngine.Execute*来运行代码。使用ScriptEngine.CreateScriptSourceFromFile然后调用ExecuteProgram解决了这个问题

查看以下完整解决方案:

注意:IronPython 2.7使整个过程更容易:

public void SetupEnvironment(ScriptEngine engine, out ScriptScope scope)
{
    scope = IronPython.Hosting.Python.CreateModule(engine, "__main__");
    return;
}