IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 《Python开发 - Python杂记》Python与C/C++混合编程 -> 正文阅读

[C++知识库]《Python开发 - Python杂记》Python与C/C++混合编程

Python是脚本语言,可以做的事情非常的多,本文将要讲解使用Python来调用C/C+库。

关于C/C++库的创建请看笔者以前的文章,这里只给出Window下的创建过程。

静态库和动态库(Windows版)

静态库和动态库(Linux版)

1 Windows创建动态库

1.1生成动态库

1.首先创建一个动态库工程。

在这里插入图片描述

取消预编译头,这里选择DLL。

在这里插入图片描述

2.创建头文件(.h)以及源文件(.cpp)

DynamicLib.h

#ifndef _DYNAMIC_LIB_H_
#define _DYNAMIC_LIB_H_

#include <iostream>

#define DLL_EXPORTS

#ifdef DLL_EXPORTS
#define DLL_API extern "C" __declspec(dllexport)
#else
#define DLL_API extern "C" __declspec(dllimport)
#endif

namespace DynamicLib
{
	DLL_API void print_hello();
}
#endif // _DYNAMIC_LIB_H_

DynamicLib.cpp

#include "DynamicLib.h"

DLL_API  void DynamicLib::print_hello()
{
	std::cout << "Hello world!" << std::endl;
}

【注1】__declspec(dllexport)是导出符号,也就是定义需要导出函数的dll中给导出函数的函数声明前面加上导出符号,表示该方法可以导出给其他DLL或者exe使用
【注2】C++的代码加extern “C”,是为了保证编译时生成的函数名不变,这样动态调用dll时才能找到相应的函数

3.选择release生成解决方案,这里选择64位。

在这里插入图片描述

最后生成的库如下图所示:

在这里插入图片描述

好了,动态库就创建好了。

1.2 dumpbin工具的使用

dumpbin.exe为Microsoft COFF二进制文件转换器,它显示有关通用对象文件格式(COFF)二进制文件的信息。可用使用dumpbin检查COFF对象文件、标准COFF对象库、可执行文件和动态链接库等

dumpbin.exe所在路径是VS安装目录\VC\bin\dumpbin.exe,也可以通过开始菜单里面的Visual Studio开发人员命令提示来运行。

在这里插入图片描述

dumpbin使用方式:

dumpbin [选项] [文件名]

在这里插入图片描述

其中多个选项间用空格分开,多个文件名间也用空格分开,文件名可以为后缀为.obj、.lib、.dll、.exe,如果没有指定任何输入文件,它将列出所有的选项。

选项说明:参数的使用可以用”-”或者”/”(如-ALL等于/ALL)后面跟选项名。有些选项可以在选项名后接”:”。使用空格或制表符(Tab)分割命令选项。选项名,关键字和文件名是不区分大小写的。大多数的参数可以应用于所有的二进制文件,有少部分参数只能用于特定的文件。

(1)/ALL :此选项显示除代码反汇编外的所有可用信息。使用/DISASM显示反汇编。可以与/ALL一起使用/RAWDATA:NONE来省略文件的原始二进制详细资料。

(2)/ARCHIVEMEMBERS:此选项显示有关库成员对象的最少信息。 (3)、/CLRHEADER file:其中file为用/clr生成的图像文件。CLRHEADER显示有关在任何托管程序中使用的.net头的信息。输出显示.net头及其中各节的位置和大小(以字节计算)。

(3)/DIRECTIVES:此选项转储图像中由编译器生成的.directive节。

(4)/DEPENDENTS:转储图像从中导入函数的DLL的名称。不要转储导入函数名。

(5)/DISASM:此选项显示代码段的反汇编,如果出现在文件中则使用符号。

(6)/EXPORTS:此选项显示从可执行文件或DLL导出的所有定义。

(7)/FPO:此选项显示框架指针优化(FPO)记录。

(8)/HEADERS:此选项显示文件头和每节的头。当用于库时,显示每个成员对象的头。

(9)/IMPORTS[:file]:此选项显示导入到可执行文件或DLL的DLL列表(静态链接的和延迟加载)和上述每个DLL的各个导入。可选file规范允许指定仅显示某个DLL的导入。

(10)/LINENUMBERS:此选项显示COFF行号。如果对象文件是用程序数据库(/Zi)、C7兼容(/Z7)或仅限行号(/Zd)编译的,则它包含行号。如果可执行文件或DLL是与生成调试信息(/DEBUG)链接的,则它包含COFF行号。

(11)/LINKERMEMBER[:{1|2}]:此选项显示库中定义的公共符号。指定参数1将按对象顺序显示符号及其偏移量。指定参数2将显示对象的偏移量和索引号,然后按字母顺序列车这些符号及每个符号的对象索引。若要两个输出都获得,指定不带数字参数的/LINKERMEMBER。

(12)/LOADCOMFIG:此选项转储IMAGE_LOAD_CONFIG_DIRECTORY结构,此结构是由WindowsNT加载程序使用并在WIINNT.H中定义的可选结构。

(13)/OUT:filename:此选项指定输出的filename。默认情况下,DUMPBIN将信息显示到标准输出。

(14)/PDBPATH[:VERBOSE]filename:filename为要为其查找匹配.pdb文件的.dll或.exe文件名。VERBOSE(可选)为报告曾尝试在其中定位.pdb文件的所有目录。/PDBPATH将沿调试器搜索.pdb文件的同一路径搜索计算机,并将报告那些.pdb文件(若有)和filename中指定的文件相对应。

(15)/RAWDATA[:{1|2|4|8|NONE}[,number]]:此选项显示文件中每节的原始内容。参数说明:1,默认值,内容以十六进制字节显示,如果内容具有打印的表示形式,则还显示为ASCII字符;2,内容显示为十六进制的2字节值;4,内容显示为十六进制的恶4字节值;8,内容显示为十六进制的8字节值;NONE,取消显示原始数据,此参数对控制/ALL输出很有用;number,显示的行被设置为每行具有number个值的宽度。

(16)/RELOCATIONS:此选项显示对象或图像中的任何重定位。

(17)/SECTION:section:此选项限制与指定的section有关的信息的输出。

(18)/SUMMARY:此选项显示有关节的最少信息(包括总大小)。如果未指定其它选项,则此选项为默认值。

(19)/SYMBOLS:此选项显示COFF符号表。符号表存在于所有对象文件中。而对于图像文件,只有当它是与/DEBUG链接时,它才包含COFF符号表。

(20)/UNWINDINFO:在程序图像(例如exe和dll)中转储结构化异常处理(SHE)表的展开描述符。/UNWINDINFO仅适用于IA64图像。

完整的选项可移步至MSDN文档查看。

dumpbin

本文主要用dumpbin查看动态库函数:

#dumpbin -exports xxx.dll

在这里插入图片描述

从上图可以看出动态库导出了1个函数,与上面代码中的导出函数一致。

值得注意的是,要想导出动态库,就需要加extern “C” 语句,否则C++会按照自己的规则篡改函数的名称。C++支持函数重载,就是在函数名字改编阶段记录下函数的相关参数信息。C++标准并没有定义名字改编的标准,因此会导致不同编译器编译出来的动态库不能通用。

而C标准规定了名字改编的标准,extern "C"告诉编译器在编译代码是按照C的标准进行编译。我相信很多做嵌入式的朋友都看到过extern "C"语句。。

另外需要注意,extern "C"修饰的函数进行了重载,则会在编译时报错,因为C语言并不支持函数的重载。




2 Python调用C/C++动态库

Python调用动态库是通过ctypes这个内建的包。ctypes提供了C的兼容数据类型,允许调用DLL或者共享库中的函数。通过该模块能可以使用Python的代码对这些库进行调用,非常方便。

ctypes 适合于“中轻量级”的Python C/C++混合编程。特别是遇到第三方库提供动态链接库和调用文档,且没有编译器或编译器并不互相兼容的场合下,使用ctypes特别方便。值得注意的是,对于某种需求,在Python本身就可以实现的情况下(例如获取系统时间、读写文件等),应该优先使用Python自身的功能而不要使用操作系统提供的API接口,否则你的程序会丧失跨平台的特性。

ctypes官方文档

Python类型和C语言类型的对应关系:

在这里插入图片描述

该表格列举了ctypes、c和python之间基本数据的对应关系,在定义函数的参数和返回值时,需记住几点:

1.必须使用ctypes的数据类型。
2.参数类型用关键字argtypes定义,返回类型用restype定义,其中argtypes必须是一个序列,如tuple或list,否则会报错。
3.若没有显式定义参数类型和返回类型,Python默认为int型。Python在调用动态库中的函数时需要指定函数的参数类型和返回值类型。通过Objdll._FuncPtr.restype来指定动态库函数的返回值类型,通过Objdll._FuncPtr.argtypes来指定动态库函数的参数类型,Objdll._FuncPtr.argtypes的类型为turple,包含动态库函数的参数类型列表,指定的参数类型必须为C/C++中参数类型所对应的ctypes类型。

好了,下面直接看Python调用动态库例子吧。

import platform
import ctypes

suffixNmae = {
    "Windows":".dll",
    "Linux":".so"
}

libPath = './lib/x64/DynamicLib' + suffixNmae[platform.system()]

# 加载动态库
objDll = ctypes.cdll.LoadLibrary(libPath)


if __name__ == '__main__':
    
    ## 调用print_hello
    objDll.print_hello()

运行结果如下:
在这里插入图片描述

结果和使用C是一样的。

下面以不同的参数类型来讲解如何使用Python代用动态库。


2.1值类型

对于参数类型和返回值类型都为值类型的动态库函数,操作相对简单,只需要指定对应的参数和返回值ctype类型即可进行调用。

C/C++代码:

class Math {

public:
	int add(int a, int b);

};

int Math::add(int a, int b)
{
	return a + b;
}

C++的函数调用使用需要extern "C"来辅助,也就是说还是只能调用C函数,不能直接调用方法,但是能解析C++方法。不是用extern “C”,构建后的动态链接库没有这些函数的符号表。

//C math
Math mathObj;
DLL_API int add(int a, int b)
{
	return mathObj.add(a, b);
}

Python代码:

import platform
import ctypes

suffixNmae = {
    "Windows":".dll",
    "Linux":".so"
}

libPath = './lib/x64/DynamicLib' + suffixNmae[platform.system()]

# 加载动态库
objDll = ctypes.cdll.LoadLibrary(libPath)

if __name__ == '__main__':
    
    # 定义函数参数
    nA = ctypes.c_int(2)
    nB = ctypes.c_int(3)
    # 指定函数返回值类型
    objDll.add.restype = ctypes.c_int
    
    # 指定函数的参数类型
    objDll.add.argtypes = (ctypes.c_int, ctypes.c_int, )
    
    # 调用函数
    res = objDll.add(nA, nB)
    print('C : sum = ', res)

运行结果如下:
在这里插入图片描述

为了简单,下面的代码将使用C编写。



2.2指针类型

创建ctypes类型的指针需要借助三个相关的函数:

在这里插入图片描述

byref相当于C的取地址符号,在参数传递时可以通过byref传递函数的指针。pointer的POINTER的区别是,pointer返回的是一个实例,而POINTER返回的是一个类型。

【例1】
C/C++代码:

DLL_API int max(uint32_t a, uint32_t b, uint32_t *maxNum)
{
	*maxNum = a > b ? a : b;

	return 0;
}

Python代码:

import platform
import ctypes

suffixNmae = {
    "Windows":".dll",
    "Linux":".so"
}

libPath = './lib/x64/DynamicLib' + suffixNmae[platform.system()]

# 加载动态库
objDll = ctypes.cdll.LoadLibrary(libPath)

if __name__ == '__main__':
    
    # 定义函数参数
    nA = ctypes.c_uint32(2)
    nB = ctypes.c_uint32(3)
    
    nMax = ctypes.c_uint32(0)
    
    # 指定函数返回值类型
    objDll.max.restype = ctypes.c_int
    
    # 指定函数的参数类型
    objDll.max.argtypes = (ctypes.c_uint32, ctypes.c_uint32, ctypes.POINTER(ctypes.c_uint32), )
    
    # 调用函数
    res = objDll.max(nA, nB, ctypes.byref(nMax))
    
    maxValue = nMax.value
    
    print('C : max = ', maxValue)

运行结果如下:

在这里插入图片描述

【例2】求和
C/C++代码:

//DLL_API int sum(uint32_t nArr[], uint32_t nLength, uint32_t *nSum)
DLL_API int sum(uint32_t *nArr, uint32_t nLength, uint32_t *nSum)
{
	if (nArr == nullptr)
	{
		return -1;
	}
	uint32_t i;
	*nSum = 0;

	for (i = 0; i < nLength; i++)
	{
		*nSum += nArr[i];
	}

	return 0;
}

Python代码:

import platform
import ctypes
import numpy as np

suffixNmae = {
    "Windows":".dll",
    "Linux":".so"
}

libPath = './lib/x64/DynamicLib' + suffixNmae[platform.system()]

# 加载动态库
objDll = ctypes.cdll.LoadLibrary(libPath)

if __name__ == '__main__':
    
    data = np.array([[0, 1, 2, 3]], dtype=np.uint32)
    
    # 定义函数参数
    nArr = data.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))
    
    nLength = ctypes.c_uint32(4)
    
    nSum = ctypes.c_uint32(0)
    
    # 指定函数返回值类型
    objDll.sum.restype = ctypes.c_int
    
    # 指定函数的参数类型
    objDll.sum.argtypes = (ctypes.POINTER(ctypes.c_uint32), ctypes.c_uint32, ctypes.POINTER(ctypes.c_uint32), )
    
    # 调用函数
    res = objDll.sum(nArr, nLength, ctypes.byref(nSum))
    
    sumValue = nSum.value
    
    print('C : sum = ', sumValue)

运行结果如下:

在这里插入图片描述

Python调用sum函数时,第一个参数需要传递指针,而以下语句返回就是指针的地址:

nArr = data.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))

在这里插入图片描述

当然还有以下方式:

import platform
import ctypes
import numpy as np

suffixNmae = {
    "Windows":".dll",
    "Linux":".so"
}

libPath = './lib/x64/DynamicLib' + suffixNmae[platform.system()]

# 加载动态库
objDll = ctypes.cdll.LoadLibrary(libPath)


if __name__ == '__main__':
    
    data = np.array([[0, 1, 2, 3]], dtype=np.uint32)
    
    # 定义函数参数
    nArr = data.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32)).contents
    
    print('nArr : ', nArr)
    nLength = ctypes.c_uint32(4)
    
    nSum = ctypes.c_uint32(0)
    
    # 指定函数返回值类型
    objDll.sum.restype = ctypes.c_int
    
    # 指定函数的参数类型
    objDll.sum.argtypes = (ctypes.POINTER(ctypes.c_uint32), ctypes.c_uint32, ctypes.POINTER(ctypes.c_uint32), )
    
    # 调用函数
    res = objDll.sum(ctypes.byref(nArr), nLength, ctypes.byref(nSum))
    
    sumValue = nSum.value
    
    print('C : sum = ', sumValue)

运行结果如下:
在这里插入图片描述

【例3】
C/C++代码:

//sort
DLL_API int bubble_sort(uint32_t *nOldArr, uint32_t nLen, uint32_t *nNewArr)
{
	int i, j, temp;

	for (i = 0; i < nLen; i++)
	{
		nNewArr[i] = nOldArr[i];
	}

	for (i = 0; i < nLen - 1; i++)
	{
		for (j = 0; j < nLen - 1 - i; j++)
		{
			if (nNewArr[j] > nNewArr[j + 1])
			{
				temp = nNewArr[j];
				nNewArr[j] = nNewArr[j + 1];
				nNewArr[j + 1] = temp;
			}
		}
	}
	return 0;
}

Python代码:

import platform
import ctypes
import numpy as np

suffixNmae = {
    "Windows":".dll",
    "Linux":".so"
}

libPath = './lib/x64/DynamicLib' + suffixNmae[platform.system()]

# 加载动态库
objDll = ctypes.cdll.LoadLibrary(libPath)

if __name__ == '__main__':
    
    data = np.array([[10, 2, 15, 3, 56]], dtype=np.uint32)
    
    # 定义函数参数
    nOldArr = data.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32)).contents
    
    print('nOldArr : ', nOldArr)
    
    nLen = ctypes.c_uint32(5)
    
    nNewArr = (5 * ctypes.c_uint32)()
    
    # 指定函数返回值类型
    objDll.bubble_sort.restype = ctypes.c_int
    
    # 指定函数的参数类型
    objDll.bubble_sort.argtypes = (ctypes.POINTER(ctypes.c_uint32), ctypes.c_uint32, ctypes.POINTER(ctypes.c_uint32), )
    
    # 调用函数
    res = objDll.bubble_sort(ctypes.byref(nOldArr), nLen, nNewArr)
    
    print(nNewArr[0], ' ', nNewArr[1], ' ', nNewArr[2], ' ', nNewArr[3], ' ', nNewArr[4])

运行结果如下:
在这里插入图片描述

C代码的最后一个参数是一个数组,Python中就需要构建一个数组,将其地址传到C函数中。

2.3结构体类型

【例1】
C/C++代码:

//结构体
typedef struct {
	int nX;
	int nY;
	int nZ;
}STPoint;

DLL_API int sum_square(STPoint *stPoint, uint32_t *nSum)
{
	if (stPoint == nullptr)
	{
		return -1;
	}

	*nSum = ((stPoint->nX) * (stPoint->nX) + (stPoint->nY) * (stPoint->nY) + (stPoint->nZ) * (stPoint->nZ));

	return 0;
}

Python代码:

import platform
import ctypes

suffixNmae = {
    "Windows":".dll",
    "Linux":".so"
}

libPath = './lib/x64/DynamicLib' + suffixNmae[platform.system()]

# 加载动态库
objDll = ctypes.cdll.LoadLibrary(libPath)

class STPoint(ctypes.Structure):
    _fields_ = [("nX", ctypes.c_int), ("nY", ctypes.c_int), ("nZ", ctypes.c_int)] 

if __name__ == '__main__':
    
    stPoint = STPoint()
    
    stPoint.nX = 2
    stPoint.nY = 3
    stPoint.nZ = 4
    
    nSum = ctypes.c_uint32()
    
    # 指定函数返回值类型
    objDll.sum_square.restype = ctypes.c_int
    
    # 指定函数的参数类型
    objDll.sum_square.argtypes = (ctypes.POINTER(STPoint), ctypes.POINTER(ctypes.c_uint32), )
    
    # 调用函数
    res = objDll.sum_square(ctypes.byref(stPoint), ctypes.byref(nSum))
    
    sumSquare = nSum.value
    
    print('C : sum_square = ',sumSquare)

运行结果如下:
在这里插入图片描述

【例2】
C/C++代码:

typedef struct {
	int nMax;
	int nMin;
}STMaxMin;

DLL_API int max_min(int *nArr, uint32_t nLength, STMaxMin *stMaxMin)
{
	if (nArr == nullptr)
	{
		return -1;
	}
	int i;
		
	stMaxMin->nMax = nArr[0];
	stMaxMin->nMin = nArr[0];

	for (i = 0; i < nLength; i++) 
	{
		if (nArr[i] > stMaxMin->nMax)
		{
			stMaxMin->nMax = nArr[i];
		}

		if (nArr[i] < stMaxMin->nMin)
		{
			stMaxMin->nMin = nArr[i];
		}

	}

	return 0;
}

Python代码:

import platform
import ctypes
import numpy as np

suffixNmae = {
    "Windows":".dll",
    "Linux":".so"
}

libPath = './lib/x64/DynamicLib' + suffixNmae[platform.system()]

# 加载动态库
objDll = ctypes.cdll.LoadLibrary(libPath)

class STMaxMin(ctypes.Structure):
    _fields_ = [("nMax", ctypes.c_int), ("nMin", ctypes.c_int)] 

if __name__ == '__main__':
    
    data = np.array([[10, 2, 15, 3, 56]], dtype=np.int)
    
    nArr = data.ctypes.data_as(ctypes.POINTER(ctypes.c_int))
    
    nLength = ctypes.c_uint32(5)
        
    stMaxMin = STMaxMin()
    
    # 指定函数返回值类型
    objDll.max_min.restype = ctypes.c_int
    
    # 指定函数的参数类型
    objDll.max_min.argtypes = (ctypes.POINTER(ctypes.c_int), ctypes.c_uint32, ctypes.POINTER(STMaxMin), )
    
    # 调用函数
    res = objDll.max_min(nArr, nLength, ctypes.byref(stMaxMin))
    

    print('C : max =  ',stMaxMin.nMax, 'min = ',stMaxMin.nMin )

运行结果如下:

在这里插入图片描述

Python中调用dll中方法的一般步骤:

1.使用extern c关键字和__declspec(dllexport)以及__declspec(dllimport)对dll进行包装。
2.使用ctypes库加载动态库。
3.根据C代码中数据类型和ctypes中类型的对应关系指定动态库函数的返回值类型和参数类型。
4.调用动态库中的函数。
5.对函数的返回结果进行转换成python中的类型进行使用。

【注】C语言中没有引用类型,如果动态库是由C++编写存在引用类型参数的函数,需要先用指针类型包装成C动态库。




3 Python与C/C++速度比较

很多朋友都会说,Python调用C库,这不是多此一举嘛,直接用Python写不就好啦,或者直接用C不就好啦。在回答这个问题之前,这里先给一个例子来说明,也就是前面的排序算法。
直接看代码:

# -*- coding: utf-8 -*-
"""
@file                main.py
@author              BruceOu
@version             V1.0
@date                2021-08-06
@blog                https://blog.bruceou.cn/
@Official Accounts   嵌入式实验楼
@brief               main
"""
import platform
import ctypes
import numpy as np
import time 

suffixNmae = {
    "Windows":".dll",
    "Linux":".so"
}

libPath = './lib/x64/DynamicLib' + suffixNmae[platform.system()]


def bubbleSort(arr):
    n = len(arr)
 
    # 遍历所有数组元素
    for i in range(n):
 
        # Last i elements are already in place
        for j in range(0, n-i-1):
 
            if arr[j] > arr[j+1] :
                arr[j], arr[j+1] = arr[j+1], arr[j]
                
# 加载动态库
objDll = ctypes.cdll.LoadLibrary(libPath)

isCpp = False

if __name__ == '__main__':
    
    arr = np.random.randint(low=1, high=100000, size=10000, dtype=np.uint32)
    
    data = np.array(arr, dtype=np.uint32)
    
    start = time.time()
     
    if(isCpp):
        length = data.size
        
        # 定义函数参数
        nOldArr = data.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32)).contents
        
        nLen = ctypes.c_uint32(length)
        
        nNewArr = (length * ctypes.c_uint32)()
        
        # 指定函数返回值类型
        objDll.bubble_sort.restype = ctypes.c_int
        
        # 指定函数的参数类型
        objDll.bubble_sort.argtypes = (ctypes.POINTER(ctypes.c_uint32), ctypes.c_uint32, ctypes.POINTER(ctypes.c_uint32), )
    
        # 调用函数
        res = objDll.bubble_sort(ctypes.byref(nOldArr), nLen, nNewArr)
        
        print(nNewArr[0], ' ', nNewArr[1], ' ', nNewArr[2], ' ', nNewArr[3], ' ', nNewArr[4])
        
    else:
        bubbleSort(arr)    
        print(arr[0], ' ', arr[1], ' ', arr[2], ' ', arr[3], ' ', arr[4])
    
    end = time.time()
    
    print('time : ', end- start)

看看两种语言实现的结果:

C库[isCpp=True]

在这里插入图片描述

以上两次的结果大约在0.0937s,再来看看Python的算法耗时。

Python[isCpp=False]

在这里插入图片描述

耗时为24s左右。

可以看到都不是一个数量级的,而且随着计算的复杂度越高。但是为啥又要用Python呢?Python简洁啊,库也多,花费少量时间写代码,运行时间可以通过并行GPU等手段优化,因此当我们提高代码运行速度,又想做一些C不好实现的逻辑代码时就可以使用C写算法,用Python实现逻辑,而且很多Python库都是使用C写的




欢迎访问我的网站

BruceOu的哔哩哔哩
BruceOu的主页
BruceOu的博客
BruceOu的CSDN博客
BruceOu的简书


欢迎订阅我的微信公众号

在这里插入图片描述

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-11 11:59:07  更:2021-08-11 12:04:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 9:47:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码