VS2013使用pythonnet在C#中调用.pyd文件
简单记录一下,如何借助pythonnet在VS2013中使用C#调用python函数。
1、环境配置
1、VS2013,框架.Net Framwork 4.5
2、pythonnet_py37_win
3、anaconda管理的python3.7虚拟环境及相关库
2、VS2013安装pythonnet
注意:
在VS2013中的NnGet管理器中直接搜索pythonnet是找不到的(可能是VS2013的NuGet管理器版本的问题),显示如下图。
所以我在VS2013中使用pythonnet时选择在VS2019中下载pythonnet_py37_win,之后加载到VS2013中使用。
puthonnet加载方式:
1、VS2019中随意建一个C#工程,打开NuGet包管理器
2、在NuGet解决方案中查找pythonnet,然后选择对应python版本的pythonnet(由于之后要使用.Net Framwork所以不选择standard)。要记得右上角的程序包源切换到nuget.org,不然找不到包。
3、将需要pythonnet版本安装到当前项目中,此时在项目文件夹中会生成一个packages文件夹,内部包含着pythonnet的NuGet包。
4、进入VS2013项目下,右键引用->管理NuGet程序包,将这个packages文件路径添加上,然后将此路径下pythonne_py37_win安装到当前项目中即可。
5、安装成功后,应用中会出现Python.Runtime
3、.pyd文件的生成
在这里的就不解释.pyd文件是什么了,类比一下可以简单理解为python中的dll文件。这里简单生成一个.pyd文件,可以点击参考这里。
下面定义一个简单的python函数
# MainModule.py
def ShowNum():
return 9999
将这个文件导出为一个.pyd文件
# Setup.py
import Cython.Build
import distutils.core
def py2c(file):
cpy = Cython.Build.cythonize(file, language_level=3) # 返回distutils.extension.Extension对象列表
distutils.core.setup(
name='pyd的编译', # 包名称
version="1.0", # 包版本号
ext_modules=cpy # 扩展模块
)
if __name__ == '__main__':
file = "MainModule.py"
py2c(file)
之后在命令行中执行python Setup.py build_ext --inplace,来生成.pyd文件。
注意:
1、若使用了虚拟环境,执行此命令时需要切换到对应虚拟环境下;
2、生成.pyd文件包含python版本信息,比如MainModule.cp37-win_amd64.pyd,其中.cp37-win_amd64可以省略。
4、C#调用.pyd文件
文件准备:
1、C#项目切换到x64
2、将.pyd文件,python37.dll放入到项目的bin->x64->debug文件夹中
调用:
首先,需要应用Python.Runtime命名空间
using Python.Runtime;
之后,由于使用了虚拟环境需要添加虚拟环境路径,这一部分也可以参考pythonnet官方的实例
string pathToVirtualEnv = @"D:\Anaconda3\envs\w2";
Environment.SetEnvironmentVariable("PATH", pathToVirtualEnv, EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("PYTHONHOME", pathToVirtualEnv, EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("PYTHONPATH", pathToVirtualEnv + "\\Lib\\site-packages;" + pathToVirtualEnv + "\\Lib", EnvironmentVariableTarget.Process);
PythonEngine.PythonHome = pathToVirtualEnv;
PythonEngine.PythonPath = PythonEngine.PythonPath + ";" + Environment.GetEnvironmentVariable("PYTHONPATH", EnvironmentVariableTarget.Process);
最后,.pyd文件的调用可以参考的官方示例调用,下面给出一个完整的调用示例。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;
using Python.Runtime;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string pathToVirtualEnv = @"D:\Anaconda3\envs\w2";
Environment.SetEnvironmentVariable("PATH", pathToVirtualEnv, EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("PYTHONHOME", pathToVirtualEnv, EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("PYTHONPATH", pathToVirtualEnv + "\\Lib\\site-packages;" + pathToVirtualEnv + "\\Lib", EnvironmentVariableTarget.Process);
PythonEngine.PythonHome = pathToVirtualEnv;
PythonEngine.PythonPath = PythonEngine.PythonPath + ";" + Environment.GetEnvironmentVariable("PYTHONPATH", EnvironmentVariableTarget.Process);
using (Py.GIL())
{
dynamic np = Py.Import("MainModule");
int i = np.PYDTest();
Console.WriteLine(i);
Console.ReadLine();
}
}
}
}
注意:
VS2013中,无法直接在控制台显示Python中print()函数的打印内容(VS2019可以),测试过程中需要将测试内容作为返回值接收并在控制台打印。