文章目录
- 1. c语言调用python 的步骤
- 1.1 包含头文件
- 1.2 初始化Python解释器
- 1.3 添加当前路径到sys.path 中
- 1.4 导入要调用的模块
- 1.5 获取函数对象
- 1.5.1 检查函数对象是否可被调用
- 1.6 构造参数
- 1.7 调用函数并获取返回值
- 1.8 返回值解析
- 1.9 释放引用的所有python对象
- 1.10 关闭python解释器
- 2. 调用无参函数示例
- 3. 调用有参函数示例
1. c语言调用python 的步骤
1.1 包含头文件
#include <Python.h>
1.2 初始化Python解释器
void Py_Initialize();
1.3 添加当前路径到sys.path 中
- 导入sys模块
使用 PyObject *PyImport_ImportModule(const char *name) 导入
- 获取sys.path对象
*PyObject_GetAttrString(PyObject *o, const char *attr_name) 获取
- 将当前路径.添加到sys.path中
int PyList_Append(PyObject *list, PyObject *item)
1.4 导入要调用的模块
PyObject *PyImport_ImportModule(const char *name)
1.5 获取函数对象
PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name)
1.5.1 检查函数对象是否可被调用
int PyCallable_Check(PyObject *obj)
1.6 构造参数
PyObject *Py_BuildValue(const char *format, ...)
调用此函数创建一个Python元组或者对象作为Python函数的参数,无参数不需要调用。
C和Python的数据类型转换对应的格式:
1.7 调用函数并获取返回值
PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)
1.8 返回值解析
int PyArg_Parse(PyObject *args, const char *format, ...)
1.9 释放引用的所有python对象
void Py_DECREF(PyObject *o)
1.10 关闭python解释器
void Py_Finalize()
2. 调用无参函数示例
printenv.py
# 无参函数
def fun_noparam():
print("Hello C")
getpython.c
#include <Python.h>
int main() {
/*初始化python解释器 */
Py_Initialize();
/* 添加当前路径到sys.path 中 */
// sys模块在Python中提供了对Python解释器的一些变量和功能的访问,例如命令行参数或系统路径等
PyObject *sys = PyImport_ImportModule("sys"); //从Python的标准库中导入名为sys的模块,并将返回的对象赋值给指针sys
//从sys模块对象中获取名为path的属性,并将其赋值给指针path。在Python中,sys.path是一个列表,包含了Python解释器在导入模块时会搜索的路径
PyObject *path = PyObject_GetAttrString(sys, "path");
// 使用`PyUnicode_FromString`函数将C字符串`"."`转换为一个Python的unicode对象。这里的`.`表示当前目录。
// 使用`PyList_Append`函数将上述创建的unicode对象添加到`path`列表中。在Python中,这相当于执行`sys.path.append('.'),
//即将当前目录添加到Python模块的搜索路径中。
PyList_Append(path, PyUnicode_FromString("."));
/* 导入要调用的python模块 printenv.py*/
PyObject *pModel = PyImport_ImportModule("printenv");
if (!pModel) {
// 当 Python C API 函数遇到错误时,它们通常会设置一个异常对象,但并不会自动打印错误信息。
// PyErr_Print() 函数用于检索当前线程中的异常对象,并打印其类型、值和 traceback(如果有的话)。
PyErr_Print();
printf("error: load python model faild\n");
return 1;
}
/* 获取导入模块中的函数对象 */
PyObject *pFunc = PyObject_GetAttrString(pModel, "fun_noparam");
// PyCallable_Check(pFunc) 是 Python C API 中的一个宏,用于检查一个 Python 对象是否可以被调用。
// 这个宏检查对象是否实现了 Python 的 __call__ 方法,使得它可以像函数那样被调用。
// pFunc 是一个指向 Python 对象的指针,通常是一个 PyObject* 类型的变量。
// 这个宏返回一个整数,如果对象是可调用的,返回非零值(通常是 1),否则返回 0。
if (!pFunc || !PyCallable_Check(pFunc)) {
PyErr_Print();
printf("error: python model function fun_noparam() faild\n");
return 1;
}
/* 调用fun_noParam 函数并获取返回值*/
PyObject *pValue = PyObject_CallObject(pFunc, NULL);
if (!pValue) {
PyErr_Print();
printf("error: function call faild\n");
return 1;
}
/* 释放所有引用的python对象*/
Py_DECREF(pValue);
Py_DECREF(pFunc);
Py_DECREF(pModel);
/* 关闭Python 解释器 */
Py_Finalize();
return 0;
}
编译:
gcc getpython.c -o getpyNoParam -I /usr/include/python3.10 -l python3.10
运行结果:
3. 调用有参函数示例
parameter.py
# 有参函数
def func_param(param):
print(param)
return param
getPythonParam.c
#include <Python.h>
int main() {
Py_Initialize();
PyObject *sys = PyImport_ImportModule("sys");
PyObject *path = PyObject_GetAttrString(sys, "path");
PyList_Append(path, PyUnicode_FromString("."));
PyObject *pmode = PyImport_ImportModule("parameter");
if (!pmode) {
PyErr_Print();
printf("error: load python model faild\n");
return 1;
}
PyObject *pFunc = PyObject_GetAttrString(pmode, "func_param");
if (!pFunc || !PyCallable_Check(pFunc)) {
PyErr_Print();
printf("error: python model function func_param() faild\n");
return 1;
}
// 创建一个字符串作为函数参数
char *param = "this c transmit param";
PyObject *pArgs = Py_BuildValue("(s)", param); // 构建元组
// 调用带参python 函数并获取返回值
PyObject *result = PyObject_CallObject(pFunc, pArgs);
if (!result) {
PyErr_Print();
printf("error: function call faild\n");
}
// 将返回类型转为c类型
char *resultToC = NULL;
if (!PyArg_Parse(result, "s", &resultToC)) {
PyErr_Print();
printf("error: parse return param faild\n");
}
// 打印返回值
printf("return param: %s\n", resultToC);
/* 释放所有引用的python对象*/
Py_DECREF(result);
Py_DECREF(pFunc);
Py_DECREF(pmode);
/* 关闭Python 解释器 */
Py_Finalize();
return 0;
}
编译:
gcc getpythonParam.c -o getpyParam -I /usr/include/python3.10 -l python3.10
运行结果: