如何利用c调用python代码
C语言调用python
通过C语言调用Python代码,需要先安装libpython3的 dev依赖库(不同的ubuntu版本下,python版本 可能会有差异, 比如ubuntu 22.04里是libpython3.10-dev)。 首先可以通过以下命令验证是否是否已经存在python3的dev包
dpkg -l | grep libpython3
正常会有类似如下的输出,出现"libpython3"和 "dev",如libpython3.10-dev即可
如果没有, 可以通过apt命令安装相关的dev包:
sudo apt install libpython3.10-dev
调用无参python函数
#nopara.py文件
def say_funny():
print('funny')
用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 *PyObject_CallObject(PyObject *callable, PyObject *args)函数调用 Python函数,并获取返回值。
- 使用void Py_DECREF(PyObject *o)函数释放所有引用的Python对象。
- 结束时调用void Py_Finalize()函数关闭Python解释器。 相关的函数参数说明参考网站(网站左上角输入函数名即可开始搜索)。
#include<Python.h>
int main(int argc, char const *argv[])
{
Py_Initialize();
PyObject *sys = PyImport_ImportModule("sys");
PyObject *path = PyObject_GetAttrString(sys,"path");
PyList_Append(path,PyUnicode_FromString("."));
PyObject *pModule = PyImport_ImportModule("nopara");
if(!pModule){
PyErr_Print();
printf("ERROR:failed to load nopara.py\n");
}
PyObject *pFunc = PyObject_GetAttrString(pModule,"say_funny");
if(!pFunc || !PyCallable_Check(pFunc))
{
PyErr_Print();
printf("ERROR:function say_funny not found or not callable\n");
return 1;
}
PyObject *pValue = PyObject_CallObject(pFunc,NULL);
if(!pValue)
{
PyErr_Print();
printf("ERROR: function call failed\n");
return 1;
}
Py_DECREF(pValue);
Py_DECREF(pFunc);
Py_DECREF(pModule);
Py_Finalize();
return 0;
}
调用有参python函数
定义一个带参数和返回值的函数
#para.py
def say_funny(category):
print(category)
return category
用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, ... x )函数将C类型的数据结构转换成 Python对象,作为Python函数的参数,没有参数不需要调用
这里要注意的是,Py_BuildValue的第一个参数是类型转换:C对应的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解释器。 相关的函数参数说明参考网站(网站左上角输入函数名即可开始搜索)。
示例代码
#include<Python.h>
int main(int argc, char const *argv[])
{
Py_Initialize();
// 将当前路径添加到sys.path中
PyObject *sys = PyImport_ImportModule("sys");
PyObject *path = PyObject_GetAttrString(sys,"path");
PyList_Append(path,PyUnicode_FromString("."));
// 导入para模块
PyObject *pModule = PyImport_ImportModule("para");
if(!pModule){
PyErr_Print();
printf("ERROR:failed to load para.py\n");
}
//获取say_funny函数对象
PyObject *pFunc = PyObject_GetAttrString(pModule,"say_funny");
if(!pFunc || !PyCallable_Check(pFunc))
{
PyErr_Print();
printf("ERROR:function say_funny not found or not callable\n");
return 1;
}
//创建一个字符串作为参数
char *category = "comedy";
PyObject *pArgs = Py_BuildValue("(s)",category);
//调用say_funny函数并获取返回值
PyObject *pValue = PyObject_CallObject(pFunc,pArgs);
if(!pValue)
{
PyErr_Print();
printf("ERROR: function call failed\n");
return 1;
}
//将返回值转换为C类型
char *result = NULL;
if(!PyArg_Parse(pValue,"s",&result))
{
PyErr_Print();
printf("Error: parse failed\n");
}
//打印返回值
printf("pValue=%s\n",result);
//释放所有引用的Python对象
Py_DECREF(pValue);
Py_DECREF(pFunc);
Py_DECREF(pModule);
//释放所有引用的Python对象
Py_Finalize();
return 0;
}