环境搭建与测试
如果想要在C语言中调用python的代码,需要安装libpython3的dev依赖库
安装:libpython3的dev依赖库
通过以下命令查看是否已经存在依赖包:
dpkg -l | grep libpython3
可见并不存在后缀为“-dev” 的库,因此需要执行以下指令安装:
sudo apt install libpython3.10-dev
安装完成后再次查看就可以看到“libpython3.10-dev”了:
测试 :C语言执行python代码
test.c
#include "Python.h" //Python API的头文件,用于访问Python对象和函数
int main()
{
Py_Initialize(); //初始化Python解释器,这样可以在C程序中执行Python代码
PyRun_SimpleString("print('successful')"); //执行一段简单的Python代码
Py_Finalize(); //关闭Python解释器,并释放资源
}
编译语句:
gcc test.c -I /usr/include/python3.10 -l python3.10
//“-I”指定python头文件路径;“-l”指定python库文件路径
输出结果:
C语言执行python函数
步骤大体如下(按顺序用对函数和参数,无技巧可言)
- 包含Python.h头文件,以便使用Python API
- 使用void Py_Initialize()初始化Python解释器
- 使用 PyObject *PyImport_ImportModule(const char *name) 和 PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name) 获取sys.path对象,并利用int PyList_Append(PyObject *list, PyObject *item)将当前路径.添加到sys.path中,以便加载当前的 Python模块(Python文件即python模块)
- 使用PyObject *PyImport_ImportModule(const char *name)函数导入Python模块,并检查是否有错误
- 使用PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name)函数获取 Python函数对象,并检查是否可调用
- 使用PyObject *Py_BuildValue(const char *format, ...)函数将C类型的数据结构转换成Python对 象,作为Python函数的参数, 没有参数则不需要调用
- 使用PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)函数调用Python 函数,并获取返回值
- 使用int PyArg_Parse(PyObject *args, const char *format, ...)函数将返回值转换为C类型, 并检查是否有错误, 没有返回值时则不需要调用
- 使用void Py_DECREF(PyObject *o)函数释放所有引用的Python对象
- 结束时调用void Py_Finalize()函数关闭Python解释器
6和7是操作Python有参函数时用的,对于无参函数可忽略
1、C语言调用无参Python函数
首先,单独写一个python文件,其中定义一个不带参数和返回值的函数:
nopara.py
def good_luck():
print('successful');
然后在写一个C程序来调用它:
nopara.c
#include "Python.h"//包含Python.h头文件,以便使用Python API
int main(){
Py_Initialize();//初始化Python解释器
PyObject *sys=PyImport_ImportModule("sys");
PyObject *path=PyObject_GetAttrString(sys,"path");//获取sys.path对象
PyList_Append(path,PyUnicode_FromString("."));//将当前路径添加到sys.path中,以便加载当前Pythn模块(Python文件)
PyObject *pModule=PyImport_ImportModule("nopara");//导入Python模块,并检查是否有误
if(!pModule){
PyErr_Print();
printf("Error:failed to load nopara.py\n");
}
PyObject *pFun=PyObject_GetAttrString(pModule,"good_luck");//获取Python函数对象,并检查是否可调用
if(!pFun){
PyErr_Print();
printf("Error:failed to load good_luck\n");
}
PyObject *pValue=PyObject_CallObject(pFun,NULL);//调用Python函数,并获取返回值
if(!pValue){
PyErr_Print();
printf("Error:failed to load pFun\n");
}
Py_DECREF(pValue);//释放所有引用的Python对象
Py_DECREF(pFun);
Py_DECREF(pModule);
Py_Finalize();//关闭Python解释器
return 0;
}
编译语句:
gcc nopara.c -I /usr/include/python3.10 -l python3.10
//“-I”指定python头文件路径;“-l”指定python库文件路径
输出结果:
2、C语言调用有参Python函数
首先,单独写一个python文件,其中定义一个带参数和返回值的函数:
para.py
def good_luck(s):
print(s)
return s
然后在写一个C程序来调用它:
para.c
#include "Python.h"//包含Python.h头文件,以便使用Python API
int main(){
Py_Initialize();//初始化Python解释器
PyObject *sys=PyImport_ImportModule("sys");
PyObject *path=PyObject_GetAttrString(sys,"path");//获取sys.path对象
PyList_Append(path,PyUnicode_FromString("."));//将当前路径添加到sys.path中,以便加载当前Pythn模块(Python文件)
PyObject *pModule=PyImport_ImportModule("para");//导入Python模块,并检查是否有误
if(!pModule){
PyErr_Print();
printf("Error:failed to load para.py\n");
}
PyObject *pFun=PyObject_GetAttrString(pModule,"good_luck");//获取Python函数对象,并检查是否可调用
if(!pFun){
PyErr_Print();
printf("Error:failed to load good_luck\n");
}
char *category="comedy";
PyObject *pArgs=Py_BuildValue("(s)",category);//创建一个Python元组,作为Python函数的参数
PyObject *pValue=PyObject_CallObject(pFun,pArgs);//调用Python函数,并获取返回值
if(!pValue){
PyErr_Print();
printf("Error:failed to load pFun\n");
}
char *result=NULL;//用指针来接收返回值
if(!PyArg_Parse(pValue,"s",&result)){
PyErr_Print();
printf("Error:parse failed\n");
}
printf("result=%s\n",result);
Py_DECREF(pValue);//释放所有引用的Python对象
Py_DECREF(pFun);
Py_DECREF(pModule);
Py_Finalize();//关闭Python解释器
return 0;
}
编译语句:
gcc para.c -I /usr/include/python3.10 -l python3.10
//“-I”指定python头文件路径;“-l”指定python库文件路径
输出结果: