Loading

如何利用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代码的流程

  1. 包含Python.h头文件,以便使用Python API。
  2. 使用void Py_Initialize()初始化Python解释器,
  3. 使用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模块)。
  4. 使用PyObject *PyImport_ImportModule(const char *name)函数导入Python模块,并检查是否 有错误。
  5. 使用PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name)函数获取 Python函数对象,并检查是否可调用。
  6. 使用PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)函数调用 Python函数,并获取返回值。
  7. 使用void Py_DECREF(PyObject *o)函数释放所有引用的Python对象。
  8. 结束时调用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代码的流程

  1. 包含Python.h头文件,以便使用Python API。

  2. 使用void Py_Initialize()初始化Python解释器,

  3. 使用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模块)。

  4. 使用PyObject *PyImport_ImportModule(const char *name)函数导入Python模块,并检查是否 有错误。

  5. 使用PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name)函数获取 Python函数对象,并检查是否可调用。

  6. 使用PyObject *Py_BuildValue(const char *format, ... x )函数将C类型的数据结构转换成 Python对象,作为Python函数的参数,没有参数不需要调用

    这里要注意的是,Py_BuildValue的第一个参数是类型转换:C对应的Python的数据类型转换对应的格式 如下:

  7. 使用PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)函数调用 Python函数,并获取返回值。

  8. 使用int PyArg_Parse(PyObject *args, const char *format, ...)函数将返回值转换为C类 型,并检查是否有错误,没有返回值时不需要调用。

  9. 使用void Py_DECREF(PyObject *o)函数释放所有引用的Python对象。

  10. 结束时调用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;
}
posted @ 2024-04-04 18:54  ⭐⭐-fighting⭐⭐  阅读(727)  评论(0编辑  收藏  举报