Python 提供了丰富的 C API 函数,我们使用这些 C API 函数可以实现将 Python 文件中的函数、类等在 C/C++ 文件中进行调用,从而使得我们可以方便地使用 Python 代码来帮助我们实现一些额外的需求(如:嵌入神经网络模型)。
网上已经有很多介绍如何将 Python 嵌入到 C/C++ 的博客,这里不再累述。这里主要叙述一下如何实现多维数组在 Python 文件和 C/C++文件间互传,即如何从 Python 文件中返回 Numpy 数组,已经如何从 C/C++文件中传递一个多维数组到Python文件中。在处理这个的过程中,遇到了许多的困难,查阅了许多网站,发现中文博客中对这部分的相信介绍不是很多,故特此写这篇论文(第一篇博文,不详细的地方望评论中指出,有问题也欢迎在评论中咨询)。
博文目录:
- 从 Python 文件中的函数返回 List 数组
- 从 Python 文件中的函数返回包含 Numpy Array 的 List 数组
- 向 Python 文件中的函数传递 List 数组
- 向 Python 文件中的函数传递 Numpy Array 数组
从 Python 文件中的函数返回 List 数组:
如果我们在 C/C++ 文件中调用的 Python 函数返回的是 List 数组,那么我们这里主要用到的是 Python C API 中的 List Object 来处理返回的数据,主要用到 List Object 里面的这些函数:
- int PyList_Check(PyObject *list)函数判断一个 PyObject 指针对象是不是一个 List 对象;
- Py_ssize_t PyList_Size (PyObject *list) 函数计算一个 List 对象的大小;
- PyObject* PyList_GetItem(PyObject *list, Py_ssize_t index) 函数返回 List对象中第 index 个元素的 PyObject 指针。
示例:假设我们有这么一个Python函数:
def IntegerListReturn():
IntegerList = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
return IntegerList
我们在 C/C++ 文件中调用这个 Python 函数时,将返回 List 对象,那么我们将在 C/C++文件中进行如下的接收操作:
// some code omitted...
cout<<"Integer List Show:"<<endl;
PyObject *pFuncTwo = PyDict_GetItemString(pDict, "IntegerListReturn");
PyObject *FuncTwoBack = PyObject_CallObject (pFuncTwo, nullptr);//返回List对象
if(PyList_Check(FuncTwoBack)){ //检查是否为List对象
int SizeOfList = PyList_Size(FuncTwoBack);//List对象的大小,这里SizeOfList = 3
for(Index_i = 0; Index_i < SizeOfList; Index_i++){
PyObject *ListItem = PyList_GetItem(FuncTwoBack, Index_i);//获取List对象中的每一个元素
int NumOfItems = PyList_Size(ListItem);//List对象子元素的大小,这里NumOfItems = 3
for(Index_k = 0; Index_k < NumOfItems; Index_k++){
PyObject *Item = PyList_GetItem(ListItem, Index_k);//遍历List对象中子元素中的每个元素
cout << PyInt_AsLong(Item) <<" "; //输出元素
Py_DECREF(Item); //释放空间
}
Py_DECREF(ListItem); //释放空间
}
cout<<endl;
}else{
cout<<"Not a List"<<endl;
}
// some code omitted...
从 Python 文件中的函数返回包含 Numpy Array 的 List 数组
带有 Numpy Array 的 List 数组,除了上述提到的 List Object 操作函数,这里还需要用到 PyArrayObject 这个对象来处理返回的 Numpy Array。先介绍一下PyArrayObject, 这个 C API 模块来自 Numpy Module 中,所以使用这个 C API 模块前需要进行一些初始化操作:
// some code omitted...
#include <numpy/arrayobject.h> //包含 numpy 中的头文件arrayobject.h
using namespace std;
void init_numpy(){
//初始化 numpy 执行环境,主要是导入包,python2.7用void返回类型,python3.0以上用int返回类型
import_array();
}
int main()
{
Py_Initialize();
init_numpy();
// some code omitted...
做完初始化后,我们就可以使用 PyArrayObject 对象。先对PyArrayObject 对象做一个简单的介绍。PyArrayObject 实际上是一个结构体,结构体内包含四个元素,用来访问 Numpy Array 中的数据:
- int nd:Numpy Array数组的维度。
- int