通常情况下,是将C#代码共享到python脚本中,可以通过脚本调用C#的各个对象。
一、IronPythonRunner
创建IronPython运行器,可通过该运行器运行python脚本。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using IronPython.Compiler;
using IronPython.Hosting;
using IronPython.Runtime;
using Microsoft.Scripting.Hosting;
using Microsoft.Scripting.Hosting.Providers;
using Microsoft.Scripting.Runtime;
namespace IronPythonTest
{
internal class IronPythonRunner
{
public ScriptEngine Engine { get; set; }
ScriptScope _scope;
public IronPythonRunner()
{
Dictionary<string, object> options = new Dictionary<string, object>();
options["LightweightScopes"] = true;
Engine = Python.CreateEngine(options);
List<string> collectionStr = new List<string>();
collectionStr.Add(AppDomain.CurrentDomain.BaseDirectory);
//导入python库,若在脚本中不使用python库,可以不导入
string[] libPaths = new string[]
{
Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"IronPythonLib"), //
@"C:/Program Files (x86)/IronPython 2.7/Lib", // IronPython installed on PC (32 bit)
@"C:/Program Files/IronPython 2.7/Lib", // IronPython installed on PC (64 bit)
};
for (int i = 0; i < libPaths.Length; i++)
{
DirectoryInfo di = new DirectoryInfo(libPaths[i]);
if (di.Exists)
{
collectionStr.Add(libPaths[i]);
break;
}
}
Engine.SetSearchPaths(collectionStr);
_scope = Engine.CreateScope();
}
private void AddSearchPaths(string fullFilePath)
{
ICollection<string> paths = Engine.GetSearchPaths();
if (!paths.Contains(fullFilePath))
{
string direPath = Path.GetDirectoryName(fullFilePath);
if (!string.IsNullOrWhiteSpace(direPath))
{
paths.Add(direPath);
Engine.SetSearchPaths(paths);
DirectoryInfo directory = new DirectoryInfo(direPath);
foreach (var path in directory.GetDirectories())
{
AddSearchPaths(path.FullName);
}
}
}
}
public dynamic RunScriptByPath(string fullFilePath)
{
AddSearchPaths(fullFilePath);
ScriptSource source = Engine.CreateScriptSourceFromFile(fullFilePath);
return RunScript(source);
}
public dynamic RunScriptByString(string pythonCodeStr)
{
ScriptSource source = Engine.CreateScriptSourceFromString(pythonCodeStr);
return RunScript(source);
}
private dynamic RunScript(ScriptSource source)
{
PythonCompilerOptions pco = (PythonCompilerOptions)Engine.GetCompilerOptions(_scope);
pco.ModuleName = "__main__";
pco.Module |= ModuleOptions.Initialize;
CompiledCode code = source.Compile(pco);
return code.Execute(_scope);
}
public void ShareVariableToScript(string name, object value)
{
IEnumerable<string> variables = _scope.GetVariableNames();
if (!variables.Contains(name))
{
_scope.SetVariable(name, value);
}
}
public Scope CustomImportModule(string moduleName, string scriptPath)
{
string rawScript = File.ReadAllText(scriptPath);
ScriptScope scopetemp = Engine.CreateScope();
var varNames = scopetemp.GetVariableNames();
foreach (var kv in _scope.GetItems())
{
if (!varNames.Contains(kv.Key) && kv.Value != null)
{
scopetemp.SetVariable(kv.Key, kv.Value);
}
}
Engine.Execute(rawScript, scopetemp);
Scope ret = HostingHelpers.GetScope(scopetemp);
_scope.SetVariable(moduleName, ret);
return ret;
}
}
}
二、PythonModel
创建要传入python脚本的类。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IronPythonTest
{
public class PythonModel
{
public event Action<string> SendMessageEvent;
public event Func<List<int>, int?> AddEvent;
public string Name { get; set; }
public int? Add(int a, int b)
{
return AddEvent?.Invoke(new List<int> { a, b });
}
public void GetValue(ref float arg1, out float? arg2, out List<int> arg3)
{
arg1 = 3.4f;
arg2 = null;
arg3 = new List<int> { 1, 3 };
SendMessageEvent?.Invoke($"GetValue:arg1 = {arg1},arg2 = {arg2},arg3 = {string.Join(",", arg3)}");
}
public void SetValue(int[] arg1)
{
SendMessageEvent?.Invoke($"SetValue:{string.Join(",", arg1)}");
}
}
}
三、Program
创建控制台程序,实例化IronPythonRunner,并将PythonModel对象传入脚本中。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IronPythonTest
{
internal class Program
{
static void Main(string[] args)
{
PythonModel pythonModel = new PythonModel();
IronPythonRunner runner = new IronPythonRunner();
runner.ShareVariableToScript("VM", pythonModel);
runner.ShareVariableToScript("WL", new Action<string>((str) =>
{
Console.WriteLine(str);
}));
runner.RunScriptByPath("test.py");
Console.ReadKey();
}
}
}
四、test.py
创建test.py脚本
# !/usr/bin/python
# -*- coding: UTF-8 -*-
import System
import clr
from System import Array
from System.Collections.Generic import List
#获取代码传送到脚本的变量
vm = globals().get('VM')
wl = globals().get('WL')
#当然也可以直接使用
WL('Start')
def writeline(str):
wl(str)
def add(lista):
res = 0
for a in lista:
res += a
wl('res = ' + str(res))
return res
#订阅事件
vm.SendMessageEvent += writeline
vm.AddEvent += add;
vm.SetValue(Array[int]([3,2,1])) #定义一个整型数组
vm.Add(2,3)
#对应ref或out参数,需用clr.StrongBox定义
arg1 = clr.StrongBox[System.Single]() #定义强类型float
arg2 = clr.StrongBox[System.Nullable[System.Single]]() #定义强类型float?
arg3 = clr.StrongBox[List[System.Int32]]() #定义强类型List<int>
vm.GetValue(arg1, arg2, arg3)
标签:Engine,string,C#,System,using,IronPython,public From: https://www.cnblogs.com/bridgew/p/16620018.html