06-09-2025, 01:37 PM
It may be necessary to upgrade csc.exe, as the system's default C# 5 cannot execute the following code.
demo:
https://i.ibb.co/chzkdkg3/pycall.gif
Function Pynet2
demo:
https://i.ibb.co/chzkdkg3/pycall.gif
Function Pynet2
out
CsScript x
str Opt=
;searchDirs=$qm$
;references=System.Core;Python.Runtime.dll;Microsoft.CSharp;netstandard
;compilerOptions=/warn:1
x.SetOptions(Opt 1)
x.AddCode("")
str code=
;###pywin32
;import ctypes
;print("hello world from python!")
;
;import win32print
;print(win32print.__file__)
;
;default_printer = win32print.GetDefaultPrinter()
;print(default_printer)
x.Call("Pynet.pyCall" code)
#ret
using System;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using System.Linq;
using Python.Runtime;
using System.Collections;
using System.Collections.Generic;
public class Pynet : IDisposable
{
,Py.GILState _gil;
,PyModule _m;
,bool _shutdown;
,public static object pyCall(string code)
,{
,,,using (var pyn = new Pynet())
,,,{
,,,,pyn.Module.Exec(code);
,,,,return null;
,,,}
,}
,/// <summary>
,/// Initializes the Python engine and optionally adds code.
,/// </summary>
,/// <param name="code">If not null/"", calls <b>PyModule.Exec</b>.</param>
,/// <param name="enablePrint">Redirect the output of the Python's print function to console. Default true.</param>
,public Pynet(string code = null, bool enablePrint = true)
,{
,,if (!PythonEngine.IsInitialized)
,,{
,,,string pyDll = @"C:\Program Files (x86)\Quick Macros 2\python312.dll";
,,,if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("PYTHONNET_PYDLL"))) Runtime.PythonDLL = pyDll;
,,,PythonEngine.Initialize();
,,,_shutdown = true;
,,,//process.thisProcessExit += _ => PythonEngine.Shutdown(); //does not work
,,}
,,_gil = Py.GIL();
,,if (enablePrint)
,,{
,,,Module.Exec("""
import sys
class NetConsole(object):
;;;;def __init__(self, writeCallback):
;;;;;;;;self.writeCallback = writeCallback
;;;;def write(self, message):
;;;;;;;;self.writeCallback(message)
;;;;def flush(self):
;;;;;;;;pass
def setConsoleOut(writeCallback):
;;;;sys.stdout = NetConsole(writeCallback)
""");
,,,var writer = (string s) => { Console.Write(s); };
,,,Module.InvokeMethod("setConsoleOut", Python.Runtime.PyObject.FromManagedObject(writer));
,,}
,,if (!string.IsNullOrEmpty(code)) Module.Exec(code);
,}
,/// <summary>
,/// Unlocks/disposes Python objects and shuts down the engine.
,/// </summary>
,public void Dispose()
,{
,,_m?.Dispose();
,,_gil?.Dispose();
,,if (_shutdown)
,,{
,,,try { PythonEngine.Shutdown(); } //without this the process does not exit
,,,catch (System.Runtime.Serialization.SerializationException) { } //thrown when using enablePrint
,,,//.NET 9+: BinaryFormatter serialization and deserialization have been removed
,,,//catch (PlatformNotSupportedException) { }
,,}
,}
,/// <summary>
,/// Gets the result of <b>Py.CreateScope</b>.
,/// You can assign it to a <c>dynamic</c> variable and call functions defined in your Python code.
,/// </summary>
,public PyModule Module => _m ??= Py.CreateScope();
}