C/C++调用python(新手必看)

目录

1.背景介绍与编程环境

2.完整实例演示

3.问题集锦

4.总结

5.参考链接


1.背景介绍与编程环境

背景介绍:        

       近年来,python语言凭借着自身语言的简单易学(相对于其他编程语言来说)及其功能强大的函数库(还有其他优点),受到许多编程爱好者的青睐,同时十分广泛的用于人工智能算法编程中。C/C++语言是基础的编程语言,可以实现与内核的交互,提高编程质量。C/C++与python各有其编程优点。python语言开发效率高,平时需要使用python做一些任务脚本,脚本里面主要包含了任务流程所需要命令执行和返回序列,而这些命令最终是需要到c/c++编写的程序代码中执行的,所以需要在C/C++中调用和解析python脚本。

       最近项目中遇到需要用C++调用python代码的情况,在网上搜索后发现中文资料比较少。因此借此机会一边学习一边整理成文档,方便后续查阅。

编程环境:

linux操作系统

python3.5

2.完整实例演示

C调用python脚本程序:

//c_call_python.cpp
#include <python3.5/Python.h>

int main()
{
    //设定参数值
    int a = 0;
    int b = 6;

    //第一步:初始化python环境
    Py_Initialize();
    //PyRun_SimpleString()执行命令语句
    //测试python3的打印语句
    PyRun_SimpleString("print('Hello Python!')\n");
    PyRun_SimpleString("import os,sys");//执行import语句,把当前路径加入路径中,为了找到math_test.py
    PyRun_SimpleString("sys.path.append('./')");
    PyRun_SimpleString("print(os.getcwd())");//测试打印当前路径
    
    PyObject *pModule;
    PyObject *pFunction;
    PyObject *pArgs;
    PyObject *pRetValue;
    //第二步:调用math_test脚本
    pModule = PyImport_ImportModule("math_test");
    if (!pModule) {
        printf("import python failed1!!\n");
        return -1;
    }
    //第三步:查找对应math_test.py中的def mainfunc(a,b)函数
    pFunction = PyObject_GetAttrString(pModule, "mainfunc");
    if (!pFunction) {
        printf("get python function failed!!!\n");
        return -1;
    }
    //第四步:新建python中的tuple对象(构建参数)
    pArgs = PyTuple_New(2);
    //PyTuple_SetItem(pArgs, 0, Py_BuildValue(""));
    PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", a));
    PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", b));
    //第五步:调用函数
    pRetValue=PyObject_CallObject(pFunction, pArgs);

    //第六步:清空PyObject 
    Py_DECREF(pModule);
    Py_DECREF(pFunction);
    Py_DECREF(pArgs);
    Py_DECREF(pRetValue);

    if (!pModule) {
        printf("import python failed!!\n");
        return -1;
    }
    //第七步:很关键的一步,如果是多次导入PyImport_ImportModule模块
    //只有最后一步才调用Py_Finalize(),此时python全局变量一直保存着
    Py_Finalize();
    //方便查看
    while (1);

    return 0;
}

可执行python脚本1:math_util.py

#!/usr/bin/python

import sys,codecs
import time
import other as oth

def add_func(a,b):
    return (a+b) 

def sub_func(a,b):
    return (a-b)

def mainfunc(a,b):
    starttime=time.time()
    oth.funx2(a)
    print("success!")
    result_1=add_func(a,b)
    result_2=sub_func(a,b)
    print("a+b= ",result_1," a-b= ",result_2)
    endtime=time.time()
    print("spend time: ",endtime-starttime)

def  main():
    mainfunc(2,6)

if __name__ == '__main__':
    main()

可执行python脚本2:other.py

#other.py
import numpy as np
def funx2(a):
    data = [[1,2],[3,4],[5,6]]
    x = np.array(data)
    print(x)
    print("call funx2 numpy2")
    return a*2

编译命令如下:

gcc $(python3.5-config --ldflags) test3.c -o test3.out

如上提供的代码是可正确运行的。正确运行的结果如下图所示:

其中,在C调用python脚本程序中,Python_Initialize()主要是初始化python解释器。

Py_SimpleString("import sys")相当于在python中的import sys语句。

Py_SimpleString("sys.path.append('./')")是将搜索路径设置为当前目录。

Py_ImportModule("helloWorld")是利用导入文件函数将helloWorld.py函数导入。

PyObject_GetAttrString(pModule, "hello")是在pyton引用模块helloWorld.py中查找hello函数。

接着调用PyEval_CallObject(pFunc, NULL)调用hello函数。最后是清理python环境释放资源。

3.问题集锦

问题1:python脚本本身存在错误

出现如上问题的原因是python脚本本身存在错误,解决方案就是要确保你的python脚本可以运行。

问题2:python.h:没有那个文件与目录

出现如上问题的原因是找不到python.h文件

此时我的调用的头文件如上图所示,一般来说该头文件都会存在,还有一方面原因是系统中装有多个的python版本,导致程序无法判断,所以需要指定具体版本,如下图所示。当然,如果你只安装了一种版本的python,可能就不会出现该问题。

问题3.编译命令导致错误问题

编译命令有很多种形式,比如说

有时会因为编译产生一些错误,具体原因笔者还不能给出明确解释(望赐教)。在网上查找的一通,尝试了各种编译指令,最后使用如上文中所示编译指令成功编译运行。

问题4.调用第三方库时出现的问题

对于纯python程序而言,绝大部分的python自带库是可以正常调用。如果python程序中包含了其他第三方库,则调用极可能出错,且不易查明原因。

4.总结

        学习在C/C++程序中调用python脚本,可以充分利用两种程序语言的特点,取长补短,提高编程效率与质量。在C/C++中嵌入Python,可以使用Python提供的强大功能,通过嵌入Python可以替代动态链接库形式的接口,这样可以方便地根据需要修改脚本代码,而不用重新编译链接二进制的动态链接库。至少你可以把它当成文本形式的动态链接库,需要的时候还可以改一改,只要不改变接口, C++的程序一旦编译好了,再改就没那么方便了。C语言对于纯python程序而言,绝大部分的python自带库是可以正常调用。如果python程序中包含了其他第三方库,则调用极可能出错,且不易查明原因。往往一个大型的python项目,比如SSD目标检测等,都是需要调用很多第三方库,而且多模块互相交织,在实践中还是会有一些令人头大的错误出来,所以如果你只想用python项目的生成结果的话,可以通过文件进行连接。在文章中简单的介绍了C/C++程序中调用python脚本的步骤,如有问题,可以发表评论,供大家参考探讨,如有不足,请不吝赐教。

5.参考链接

https://docs.python.org/3/c-api/

 

  • 21
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值