C/C++调用Python3.6 VS2017

最近项目中需要将Python文件转化成C/C++可调用的文件,这个问题本来有两条思路可选:
1.用C/C++将Python文件重新写一遍
2.将Python文件封装成dll等可供C/C++调用的文件
因为.py代码较长,且里面调用了许多Python中的库函数,所以实现思路1实现起来相对困难,所以决定选择思路2.
对于思路2这里也有两种方案可供选择:
1.直接写C调用
2.借助Cython库完成对Python文件的封装
因为之前在用Cython时用到的坑实在太多,所以这次打算尝试一下使用方案1解决,即直接在C语言中调用Python函数。

一、入门尝试

参照博客C/C++调用Python进行入门尝试,需要注意的是头文件中include Python.h时是Python.h所在的文件路径,原博客调用的是Python2,所以这里也进行了相应的改动

/*直接include<Python.h>会报错,这里需要查看自己电脑上的Python.h所在的文件夹*/
#include <D:\Program Files\Python36\include\Python.h>


int main(int argc, char *argv[])
{
	wchar_t *program = Py_DecodeLocale(argv[0], NULL);
	Py_SetProgramName(program);
	Py_Initialize();
	PyRun_SimpleString("print('Hello Python!'\n)");
	Py_Finalize();
	system("pause");
	return 0;
}

运行结果如下:
在这里插入图片描述
不进行配置时,该代码会报 LINK : fatal error LNK1104: 无法打开文件“python36.lib” 的错误,解决该问题需要对VS进行一些配置

1. 配置库目录

在电脑中找到python36.lib所在的路径,D:\Program Files\Python36\libs\python36.lib,将该路径添加到项目属性页中>>VC++目录>>库目录中添加上述路径

2. 配置附加依赖项

在项目属性页中>>链接器>>输入>>附加依赖项中加入D:\Program Files\Python36\libs\python36.lib

3. 若配置好库目录和附加依赖项仍然报LNK1104无法打开文件“python36.lib”的错误

请检查你的python版本是32位还是64位,在相应的配置管理器中选择是Win32还是x64
在这里插入图片描述

4. 因为我这里用的是Release,所以是python36.lib,若是Debug,则对应的改为python36_d.lib,这里的36对应的是Python的版本号,若是其它版本进行相应的更改

5. 运行过程中遇到的其它错误

1. error C2664: ‘Py_SetProgramName’ : cannot convert parameter 1 from 'char ’ to 'wchar_t ’

解决方案:

wchar_t *program = Py_DecodeLocale(argv[0], NULL);
Py_SetProgramName(program);
2. 未定义标识符 PyString_FromString, PyInt_AsLong

这些错误都是由于Python的版本不同引起的,“PyString_FromString”和“PyInt_AsLong”均是Python2中的,Python3中对应的是PyUnicode_FromString和PyLong_AsLong。

二、配置验证

若上述程序能正常运行说明基本的配置没有问题,接着尝试调用一个Python文件,新建了一个下面的程序,但在程序运行的时候竟然报了找不到去python36.lib文件的错误,这是因为上述过程配置的是在上述工程项目上的属性,这里新建了一个便又遇到了这个错误,但每次都重新配置一遍太过麻烦,这里查阅资料完成了一次配置,永久可用。
方法是在你新建的项目中找到视图>>其他窗口>>属性管理器,如下图所示
在这里插入图片描述
然后再看页面右侧是属性管理器,根据你用的是Release版本还是Debug版本已经是32位还是62位选择相应的文件夹下的Microsoft.Cpp.x64.user,双击会弹出属性页窗口
在这里插入图片描述
属性页窗口如下图所示,然后按照一中提到的方法配置库目录和附加依赖项即可。
在这里插入图片描述
在一个cpp文件中放入如下代码

#include <D:\Program Files\Python36\include\Python.h>

int great_function_from_python(int a) {
	int res;
	PyObject *pModule, *pFunc;
	PyObject *pArgs, *pValue;

	/*导入great_module模块,注意要将great_module.py放入工程文件夹中的x64文件夹下的Release文件夹下*/
	pModule = PyImport_ImportModule("great_module");

	/*在great_module.py中有一个great_function函数*/
	pFunc = PyObject_GetAttrString(pModule, "great_function");

	/*创建一个python类型的变量,这里均可以创建成tuple数据类型*/
	pArgs = PyTuple_New(1);
	/*给创建的变量赋值,中间的0表示的是tuple的第0项,Py_BuildValue("i", a)中的“i”表示的是int,还可以换成"d"Double,"s"string*/
	PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", a));
	/*
	pArgs = PyTuple_New(3);
	PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", a));
	PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", a));
	PyTuple_SetItem(pArgs, 2, Py_BuildValue("i", a));
	*/

	/*传入函数所需参数pArgs,如不需传入参数则位NULL,调用函数pFunc,pValue为返回值*/
	pValue = PyObject_CallObject(pFunc, pArgs);

	/*将返回值传递给C中的变量res*/
	res = PyLong_AsLong(pValue);

	return res;
}

int main(int argc, char *argv[]) {
	Py_Initialize();
	printf("%d", great_function_from_python(10));
	Py_Finalize;
	system("pause");
	return 0;
}

其中great_module.py中代码如下,注意要将great_module.py放入到工程文件夹下的x64>>Release文件夹中,如下图所示。

def great_function(a):
    return a + 1

在这里插入图片描述
若不将great_module.py放入正确的位置,会报错误引发了异常: 读取访问权限冲突。 v 是 nullptr。 出现了… 如下图所示
在这里插入图片描述

运行程序会得到如下结果,这样便可能调用一个Python文件
在这里插入图片描述

后来有尝试了更复杂的一些Python文件,甚至在一个py文件中import了另外一个py文件,均能返回正常的结果,import许多库包如itk,cv2,PIL,skelarn等均能正常运行。
另外加入了自己写的一个库函数也能正常调用,所以前期配置好了还是很方便将py文件在C/C++中调用的。

参考链接:
C/C++ 和 Python混合编程
混合编程之——C++调用python2.7&python3.5
第十五章:C语言扩展
C/C++ 调用Python

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值