C++调用Python总结

  最近要通过开源数据集测试模型,官方标签有的不适合整理为C++格式进行处理,因此准备通过与Python混合编程实现。网上关于如何实现有很多资料,这里总结下用到的资料和遇到问题。

1、工程配置

  python是必须要装好的,这里主要说下vs的配置。
  C++调用Python脚本中的函数
  参考该博文,C++调用Python主要使用到Python安装路径下的include、libs、该目录下相关dll。设置上不需要拷贝这些文件,需要讲dll路径添加到环境变量 “Path” 中,将include文件路径添加到VS工程属性的 “包含目录” ,将libs文件夹路径添加到VS工程属性的 “库目录” ,并在工程属性 -> 链接器 -> 附件依赖项 中添加libs文件夹中相关lib文件。

2、C++ 调用Python流程

  • 首先需要包含头文件 Python.h
  • 初始化Python环境 Py_Initialize()
  • 添加模块路径(或者说脚本路径)PyRun_SimpleString()
  • 导入模块PyImport_ImportModule()
  • 导入函数PyObject_GetAttrString()
  • 使用函数PyObject_CallObject()
  • 获取结果PyArg_Parse()
  • 结束释放Py_DECREF()Py_Finalize()

3、初始化问题

Fatal Python error: Py_Initialize: unable to load the file system codec
ImportError: No module named 'encodings'

  1、初始化调用Py_Initialize()就报错,网上关于这个问题都是检查python版本有没有问题,路径是否设置对。最后通过C++调用Python Py_Initialize失败解决了问题,即添加Py_SetPythonHome(L"<Python路径>"),需要说明的是作者是添加的Scripts文件夹路径,而我添加到Python那层句可以了,相关dll也是在Python根目录下。

  2、调用 PyImport_ImportModule加载python老是返回NULL。参考c++加载python模块,但是PyImport_ImportModule老返回NULL,主要是确保“sys.path.append()”中写入了python脚本的路径,以及该脚本无错误可运行。

4、参数输入

  关于C++嵌入Python的用法在Kisser Leon的C++部分有专题博文,关于参数的输入,比较简洁的方法是用Py_BuildValue,在c++中嵌入python入门2有使用案例。

    命令 实际输入
Py_BuildValue("") None
Py_BuildValue(“i”, 123) 123
Py_BuildValue(“iii”, 123, 456, 789) (123, 456, 789)
Py_BuildValue(“s”, “hello”) ‘hello’
Py_BuildValue(“ss”, “hello”, “world”) (‘hello’, ‘world’)
Py_BuildValue(“s#”, “hello”, 4) ‘hell’
Py_BuildValue("()") ()
Py_BuildValue("(i)", 123) (123,)
Py_BuildValue("(ii)", 123, 456) (123, 456)
Py_BuildValue("(i,i)", 123, 456) (123, 456)
Py_BuildValue("[i,i]", 123, 456) [123, 456]
Py_BuildValue("{s:i,s:i}", “abc”, 123, “def”, 456) {‘abc’: 123, ‘def’: 456}
Py_BuildValue("((ii)(ii)) (ii)", 1, 2, 3, 4, 5, 6) (((1, 2), (3, 4)), (5, 6))

5、接口查看

  Python版本升级,其C API接口也可能发生改变,比如有人提到Python2中PyString_AsString在Python3中找不到了
  C API PyString_AsString在Python3.0中用什么代替了?
  而回答的PyByte_AsString 、PyUnicode_AsString在Python3.5中都没有找到,不过既然说到是通过查看Python的dll发现的,我们也可以查看自己dll中有哪些接口,查看dll的方法可以用第三方工具,也可以直接用windows自带命令:

dumpbin /exports "<DllPath>"

6、一些使用技巧总结(后续补充)

  C++调用Python获取PyObject*对象,因此可以比较灵活的传递参数,这里对学习过程中使用到的方法做一个总结。

  1、list数据使用
  Python嵌入C/C++ (Python核心编程)
  Python的list数据可以通过PyList_Size()获取size,再通过PyList_GetItem()获取每一位的数据。

PyObject* rel = PyObject_CallObject(func, args);  
int s = PyList_Size(rel);
for (int i = 0; i < s; i++)
{
	std::cout << PyUnicode_AsUTF8(PyList_GetItem(rel, i));
	std::cout  << std::endl;
}

  

  

  

发布了24 篇原创文章 · 获赞 8 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/yangjf91/article/details/93062961