最近要通过开源数据集测试模型,官方标签有的不适合整理为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;
}
更多推荐
C++调用Python总结
发布评论