返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >python+C、C++混合编程的应用
  • 681
分享到

python+C、C++混合编程的应用

python 2023-01-31 07:01:44 681人浏览 薄情痞子
摘要

TioBE每个月都会新鲜出炉一份流行编程语言排行榜,这里会列出最流行的20种语言。排序说明不了语言的好坏,反应的不过是某个软件开发领域的热门程度。语言的发展不是越来越common,而是越来越专注领域。有的语言专注于简单高效,比如python

TioBE每个月都会新鲜出炉一份流行编程语言排行榜,这里会列出最流行的20种语言。排序说明不了语言的好坏,反应的不过是某个软件开发领域的热门程度。语言的发展不是越来越common,而是越来越专注领域。有的语言专注于简单高效,比如python,内建的list,dict结构比C/C++易用太多,但同样为了安全、易用,语言也牺牲了部分性能。在有些领域,比如通信,性能很关键,但并不意味这个领域的coder只能苦苦挣扎于c/c++的陷阱中,比如可以使用多种语言混合编程

我看到的一个很好的Python与c/c++混合编程的应用是NS3(Network Simulator3)一款网络模拟软件,它的内部计算引擎需要用高性能,但在用户建模部分需要灵活易用。NS3的选择是使用C/C++来模拟核心部件和协议,用python来建模和扩展。

这篇文章介绍python和c/c++三种混合编程的方法,并对性能加以分析。

首先要说一下python只是一个语言规范,实际上python有很多实现:CPython是标准Python,是由C编写的,python脚本被编译成CPython字节码,然后由虚拟机解释执行,垃圾回收使用引用计数,我们谈与C/C++混合编程实际指的是基于CPython解释上的。除此之外,还有Jython、IronPython、PyPy、Pyston,Jython是Java编写的,使用JVM的垃圾回收,可以与Java混合编程,IronPython面向.net平台。
python与C/C++混合编程的本质是python调用C/C++编译的动态链接库,关键就是把python中的数据类型转换成c/c++中的数据类型,给编译函数处理,然后返回参数再转换成python中的数据类型。

首先,编写一段累加数值的c代码:

extern "C" 
{
    int addBuf(char* data, int num, char* outData);
}
int addBuf(char* data, int num, char* outData)
{
    for (int i = 0; i < num; ++i)
    {
        outData[i] = data[i] + 3;   
    }
    return num;
}

然后,将上面的代码编译成so库,使用下面的编译指令

>GCc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC addbuf.c -o addbuf.o

最后编写python代码,使用ctypes库,将python类型转换成C语言需要的类型,然后传参调用so库函数:

from ctypes import * # cdll, c_int
lib = cdll.LoadLibrary('libmathBuf.so')
callAddBuf = lib.addBuf
num = 4
numbytes = c_int(num)
data_in = (c_byte * num)()
for i in range(num):
    data_in[i] = i
data_out = (c_byte * num)()
ret = lib.addBuf(data_in, numbytes, data_out)   #调用so库中的函数

这种方法需要修改c/c++代码,在外部函数中处理入/出参,适配python的参数。写一段c代码将外部入参作为shell命令执行:


         #include <Python.h>
static PyObject* SpamError;
static PyObject* spam_system(PyObject* self, PyObject* args)
{
        const char* command;
        int sts;
        if (!PyArg_ParseTuple(args, "s", &command))  //将args参数按照string类型处理,给command赋值
                return NULL;
        sts = system(command); //调用系统命令
        if (sts < 0) {
                PyErr_SetString(SpamError, "System command failed");
                return NULL;
        }
        return PyLong_FromLong(sts);     //将返回结果转换为PyObject类型
}
//方法表
static PyMethodDef SpamMethods[] = {
        {"system", spam_system, METH_VARARGS,
        "Execute a shell command."},
        {NULL, NULL, 0, NULL}
};
//模块初始化函数
PyMODINIT_FUNC initspam(void)
{
        PyObject* m;
        //m = PyModule_Create(&spammodule); // v3.4
        m = Py_InitModule("spam", SpamMethods);
        if (m == NULL)
                return;
        SpamError = PyErr_NewException("spam.error",NULL,NULL);
        Py_INCREF(SpamError);
        PyModule_AddObject(m,"error",SpamError);
}

处理上所有的入参、出参都作为PyObject对象来处理,然后使用转换函数把python的数据类型转换成c/c++中的类型,返回参数按相同方式处理。比第一种方法多了初始化函数,这部分是把编译的so库当做python module所必需要做的。
python这样使用:

imoprt spam
spam.system("ls")

使用c/c++编写python扩展可以参见:Http://docs.python.org/2.7/extending/extending.html

这种方式并不能算是一种新方式,实际上是基于第二中方式的一种包装。SWIG是个帮助使用C或者C++编写的软件能与其它各种高级编程语言进行嵌入联接的开发工具。SWIG能应用于各种不同类型的语言包括常用脚本编译语言例如Perl, PHP, Python, Tcl, Ruby, phpC#,Java,R等。

操作上,是针对c/c++程序编写独立的接口声明文件(通常很简单),swig会分析c/c++源程序自动分析接口要如何包装。在指定目标语言后,swig会生成额外的包装源码文件。编译so库时,把包装文件一起编译、连接即可。看个c代码例子:

int system(const char* command)
{
        sts = system(command);
        if (sts < 0) {
                return NULL;
        }
        return sts;
}

c源码中去掉适配python的包装,仅定义system函数本身,这比第二种方式简洁很多,并且剔除了c代码与python的耦合代码,是c代码通用性更好。
然后编写swig接口声明文件spam.i:

%module spam
%{
#include "spam.h"
%}
%include "spam.h"
%include "typemaps.i"
int system(const char* INPUT);

这是一段语言无关的模块声明,要创建一个叫spam的模块,对system做一个声明,主要是声明参数作为入参使用。然后执行swig编译程序:

>swig -c++ -python spam.i

swig会生成spam_wrap.cxx和spam.py两个文件。先看spam_wrap.cxx,这个生成的文件很长,但关键的就是对函数的包装:
python+C、C++混合编程的应用
包装函数传入的还是PyObejct对象,内部进行了类型转换,最终调了源码中的system函数。
生成的了另一个spam.py实际上是对so库又用python包装了一层(实际比较多余):
python+C、C++混合编程的应用

这里使用_spam模块,这里实际上是把扩展命名为了_spam。关于swig在python上的应用可以参见:http://www.swig.org/Doc1.3/Python.html
下面就是编译和安装python 模块,Python提供了distutils module,可以很方便的编译安装python的module。像下面这样写一个安装脚本setup.py:

python+C、C++混合编程的应用

执行 python setup.py build,即可以完成编译,程序会创建一个build目录,下面有编译好的so库。so库放在当前目录下,其实Python就可以通过import来加载模块了。当然也可以用 python setup.py install 把模块安装到语言的扩展库——site-packages目录中。关于build python扩展,可以参考https://docs.python.org/2/extending/building.html#building

混合编程的使用场景中,很重要一个就是性能攸关。那么这小节将通过几个小实验验证下混合编程的性能如何,或者说怎样写程序能发挥好混合编程的性能优势。

我们使用冒泡排序算法来验证性能。

1)实验一 使用冒泡程序验证python和c/c++程序的性能差距

python版冒泡程序:

def bubble(arr,length):
    j = length - 1
    while j >= 0:
        i = 0
        while i < j:
            if arr[i] > arr[i+1]:
                tmp = arr[i+1]
                arr[i+1] = arr[i]
                arr[i] = tmp
            i += 1
        j -= 1

c语言版冒泡排序

void bubble(int* arr,int length){
    int j = length - 1;
    int i;
    int tmp;
    while(j >= 0){
        i = 0;
        while(i < j){
            if(arr[i] > arr[i+1]){
                tmp = arr[i+1];
                arr[i+1] = arr[i];
                arr[i] = tmp;
            }
            i += 1;
        }
        j -= 1;
    }
}
  使用一个长度为100内容固定的数组,反复排序10000次(每次排序后,再把数组恢复成原始序列),记录执行时间:
 在相同的机器上多次执行,Python版执行时间是10.3s左右,而c语言版本(未使用任何优化编译参数)执行时间只有0.29s左右。相比之下python的性能的确差很多(主要是python中list的操作跟c的数组相比,效率差非常多),但python中很多扩展都是c语言写的,目的就是为了提升效率,python用于数据分析的numpy库就拥有不错的性能。下个实验就验证,如果python使用c语言版本的冒泡排序扩展库,性能会提升多少。

2)实验二 python语言使用ctypes方式调用
这里直接使用c_int来定义了数组对象,这也节省了调用时数据类型转换的开销:

import time
from ctypes import *
IntArray100 = c_int * 100
arr = IntArray100(87,23,41, 3, 2, 9,10,23,0,21,5,15,93, 6,19,24,18,56,11,80,34, 5,98,33,11,25,99,44,33,78,
       52,31,77, 5,22,47,87,67,46,83, 89,72,34,69, 4,67,97,83,23,47, 69, 8, 9,90,20,58,20,13,61,99,7,22,55,11,30,56,87,29,92,67,
       99,16,14,51,66,88,24,31,23,42,76,37,82,10, 8, 9, 2,17,84,32,66,77,32,17, 5,68,86,22, 1, 0)
... ...
if __name__ == "__main__":
    libbubble = CDLL('libbubble.so')
    time1 = time.time()
    for i in xrange(100000):
        libbubble.initArr(arr1,arr,100)
        libbubble.bubble(arr1,100)
    time2 = time.time()
    print time2 - time1

再次执行:
为了减少误差,把循环增加到10万次,结果c原生程序使用优化参数编译后用时0.65s左右。python使用c扩展后(相同编译参数)执行仅需2.3s左右。
3)实验三 在c语言中使用PyObject处理入参
这种方式是在python中依然使用list装入待排序数列,在c函数中把list赋值给数组,再进行排序,排好序后,再对原始list赋值。循环排序10万次,执行用时1.0s左右。
4) 实验四 使用swig来包装c方法
在接口文件中声明%array_class(int,intArray);然后在Python中使用initArray来作为数组,同样修改成10万次排序。python版本的程序(相同编译参数)执行仅需0.7s左右,比c原生程序慢大概7%。

1.python 的list效率非常低,在高性能场景下避免对list大量循环、取值、赋值操作。如需要最好使用ctype中的数组,或者是用c语言来实现。
2.应该把耗时的cpu密集型的逻辑交给c/c++实现,python使用扩展即可。

--结束END--

本文标题: python+C、C++混合编程的应用

本文链接: https://lsjlt.com/news/191861.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • python+C、C++混合编程的应用
    TIOBE每个月都会新鲜出炉一份流行编程语言排行榜,这里会列出最流行的20种语言。排序说明不了语言的好坏,反应的不过是某个软件开发领域的热门程度。语言的发展不是越来越common,而是越来越专注领域。有的语言专注于简单高效,比如python...
    99+
    2023-01-31
    python
  • Python和C++的混合编程(使用Bo
      想要享受更轻松愉悦的编程,脚本语言是首选。想要更敏捷高效,c++则高山仰止。所以我一直试图在各种通用或者专用的脚本语言中将c++的优势融入其中。原来贡献过一篇《c++和js的混合编程》也是同样的目的。   得益于机器学习领域的发展,...
    99+
    2023-01-30
    Python Bo
  • Python 和 C++ 混合编程:pybind11 使用
    Python 和 C++ 混合编程:pybind11 使用 1. 目的需求2. pybind 11 简介3. 使用实践:一个简单的实例3.1 开发环境3.2 准备工作3.3 建立工程 test...
    99+
    2023-09-09
    python c++ 开发语言
  • C++调用Python(混合编程)函数整理总结
    文章目录 C++调用python概述相关官方文档相关函数1.初始化python解释器环境2.调用python脚本的静态简单方式3.动态加载python模块并执行函数3.1不带参数和返回值的举例...
    99+
    2023-09-03
    python c++ 开发语言
  • C与汇编混合编程的实现示例
    目录1. C语言内联汇编2. C语言调用汇编函数3. 汇编代码调用C语言函数上一期中,使用链表的方式进行对不同任务的调用,实现的效果还是不错的,但是,任务在进行过程中不能进行来回的切...
    99+
    2024-04-02
  • C++和C的混合编译的项目实践
    目录简介某企业曾经给出如下的一道面试题问题分析关于 extern “C”extern关键字用法举例静态库是什么创建C静态库尝试使用C++程序调用C静态库创建C...
    99+
    2024-04-02
  • Python调用Matlab的混合编程
    一. 配置方法: 找到Matlab安装根目录,比如D:\matlab,然后进入D:\matlab\extern\engines\python目录中,Shift+右键-->“在此处打开命令窗口”, 1.有管理员权限的,用 管理员权限执...
    99+
    2023-01-31
    Python Matlab
  • Java与C++中怎么实现混合编程
    Java与C++中怎么实现混合编程,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。实现原理实现Java和C++的交互,使用的技术是称为JNI( Java Nati...
    99+
    2023-06-17
  • c/c++单例模式类的混合编译案例详解
    目录C/C++混合编译解决方案:中间层调用log案例解决方案:源代码C/C++混合编译 难点:c++支持重载,因此g++编译后的函数名有额外信息,在gcc编译的c文件中无法识别符号,...
    99+
    2024-04-02
  • C/C++在Java、Android和Objective-C三大平台下实现混合编程
    Android和iOS开发都支持C++开发,可以一套代码多平台使用。同时C++难以反编译的特性也可以为Android开发带来代码的保密,另一native特性也可以提高代码的运行...
    99+
    2022-06-06
    c+ JAVA objective-c C++ Android
  • 混合语言编程—C#使用原生的Directx和OpenGL绘图的方法
    由于项目需要做一些图形展示,所以就想到了使用Directx和OpenGL来绘图,但项目准备使用C#来开发(大家比较熟悉C#),在网上看了相关的资料,有一些第三方的控件可用,试用了下,...
    99+
    2022-11-15
    C# Directx OpenGL
  • C语言如何与ARM汇编语言混合编程示例详解
    目录一、ARM汇编语言简介二、C语言调用汇编语言1.无参数调用2.有参数调用三、汇编语言调用C语言四、总结五、参考文献主要使用软件:keiL μVision5 一、ARM汇编语言简介...
    99+
    2024-04-02
  • Python与Matlab混合编程的实现案例
    目录前言一、环境准备二、简单示例三、更复杂的示例1.调用.m文件2.调用自定义函数3.绘图测试四、项目相关前言 因为项目需要,需要批处理很多Matlab的.m文件,从每个文件中提取结...
    99+
    2023-01-28
    Python与Matlab混合编程 Python Matlab混合编程
  • SQLite3与C/C++的结合应用
     这是前几天上面派下来的需求,说要在本地存储大约6W条数据,因为虽然webservice比较方便,但是每次请求时都要传输这6W条数据,不免有点费流量,毕竟客户端用的都是3G的笔记本。 于是就开始在网上寻求解决方案。首先想到的是XML,但后来...
    99+
    2023-01-31
  • C# interface编程怎么应用
    这篇文章主要介绍“C# interface编程怎么应用”,在日常操作中,相信很多人在C# interface编程怎么应用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C# interface编程怎么应用”的疑...
    99+
    2023-06-17
  • 批处理与python代码混合编程的方法
    批处理可以很方便地和其它各种语言混合编程,除了好玩,还有相当的实用价值,比如windows版的ruby gem包管理器就是运用了批处理和ruby的混合编写,bathome出品的命令工具包管理器bcn 使用了...
    99+
    2022-06-04
    批处理 代码 方法
  • 泛型编程在 C++ 中与设计模式的结合应用
    泛型编程和设计模式在 c++++ 中的结合提供了创建可重复、灵活且可扩展代码的方法。泛型容器(如 std::vector)允许存储任何类型的数据。泛型算法(如 std::sort)可用于...
    99+
    2024-05-14
    设计模式 泛型编程 c++
  • C++和Python,哪个更适合编程新手?
    C++和Python,哪个更适合编程新手? 随着计算机科学领域的不断发展,编程已经成为一项极具价值和魅力的技能。然而,对于初学者来说,选择一门合适的编程语言并开始学习并不容易。在众多编...
    99+
    2024-04-02
  • QT与MATLAB混合编程的详细教程
    目录QT与MATLAB混合编程一、环境二、将matlab程序写成函数形式三、将函数的.m文件转换成动态链接库形式四、QT调用1.添加外部库2.Matlab其他依赖库和头文件搜索路径的...
    99+
    2023-01-18
    qt与matlab混合编程打包 qt和matlab qt调用matlab函数
  • C++ 多线程编程中线程池的应用
    c++++ 多线程编程中使用线程池的好处包括:1)减少线程创建次数;2)负载均衡;3)避免资源争用。例如,通过使用线程池将图像转换任务分配给线程池,可以提高文件转换应用程序的转换速度。 ...
    99+
    2024-05-14
    多线程 线程池 c++ 标准库
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作