python 项目无法直接编译为 windows 原生 .dll 供 c# p/invoke 调用,但可通过 python.net 实现无缝集成:在 c# 进程内嵌入 python 运行时,直接调用 python 类、函数及第三方库(如 opencv、pandas),无需进程间通信或 exe 封装。
python 项目无法直接编译为 windows 原生 .dll 供 c# p/invoke 调用,但可通过 python.net 实现无缝集成:在 c# 进程内嵌入 python 运行时,直接调用 python 类、函数及第三方库(如 opencv、pandas),无需进程间通信或 exe 封装。
将 Python 项目“转换”为 C# 可直接引用的 .dll 并非字面意义上的编译(Python 是解释型语言,无原生 .NET IL 输出能力),但可通过 Python.NET 这一成熟桥梁实现等效效果:它允许 C# 程序在同一个进程中加载并执行 Python 代码,访问 Python 对象(包括自定义类、NumPy 数组、OpenCV cv2 模块、Pandas DataFrame 等),完全规避了 Process.Start() 的启动开销、标准流解析错误和跨进程数据序列化难题。
安装 Python.NET NuGet 包
在 C# 项目中执行:
dotnet add package Python.Runtime
或通过 Visual Studio NuGet 包管理器安装 Python.Runtime。
准备 Python 模块(无需打包)
保留原始 .py 文件(如 math_operation.py),确保其路径可被 Python 运行时发现(推荐放在项目 Resources 目录或指定路径):
# math_operation.pyclass A: def add(self, a, b): return int(a + b) # 显式转为 int,避免类型不匹配 def subtract(self, a, b): return int(a - b)
C# 中直接调用 Python 类
初始化 Python 运行时后,即可导入模块、实例化类、调用方法:
using Python.Runtime;class Program{ static void Main(string[] args) { // 初始化 Python 运行时(需指定 Python 安装路径,或让其自动发现) // 注意:Python 版本需与 Python.NET 兼容(推荐 3.8–3.11) PythonEngine.Initialize(); // 设置 Python 模块搜索路径(可选) using (Py.GIL()) // 获取全局解释器锁 { // 导入 Python 模块 dynamic mathModule = Py.Import("math_operation"); // 实例化 Python 类 dynamic pyObj = mathModule.A(); // 直接调用方法(参数自动转换,返回值自动映射) int result1 = pyObj.add(3, 4); int result2 = pyObj.subtract(10, 6); Console.WriteLine($"The sum of 3 and 4 is: {result1}"); Console.WriteLine($"The difference between 10 and 6 is: {result2}"); } PythonEngine.Shutdown(); // 清理资源(可选,进程退出时自动释放) }}
放弃 PyInstaller → EXE → Process.Start() 的低效方案,改用 Python.NET 是将 Python 逻辑深度集成进 C# 应用的工业级标准做法。它不仅解决了 null 返回、类型转换失败、环境隔离等问题,更赋予 C# 直接操作 Python 对象的能力——无论是调用 cv2.imread() 加载图像,还是将 pandas.DataFrame 转为 DataTable,均可在统一内存空间内完成。只需正确配置环境、合理管理 GIL,并注意异常与资源释放,即可构建高性能、易维护的混合应用。