Python教程

Python与C语言数据交互

本文主要是介绍Python与C语言数据交互,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

       Python语言与C语言数据交互的场景还是比较常见的,例如在使用python优秀的数据处理可视化等优势的同时,对于某些优秀的开源C/C++的软件库的调用就需要用到ctypes库函数对动态库进行API的灵活调用了,再例如在某些场景下,C语言的数据需要可视化,而C语言的可视化接口的支持是很薄弱的,这里可以采用Python强大的可视化效果来验证数据的正确性(也可以采用MATLAB完成可视化)。 再比如在某些Demo测试场景下,使用Python便捷部署的神经网络框架在使用获取内存图像数据时也可能使用到Python和C之间数据交换的需求。

一、python与C交互的重要库 ctypes

        ctypes库作为python与C之间的交互的重要库,其定义了各类数据类型与C语言中的数据类型进行对应,其中包括了char,int,POINTER等等,具体可以参看数据手册。ctypes还能够通过CDLL接口应用C语言的动态库.so,在调用接口过程中,应该要严格配置Python端调用动态库函数接口的参数类型(不能有任何偏差),应该掌握如何定义数组缓冲区并操作地址变量,同时能够使用接口获取变量地址,从而传给C-API使用,基础如下所示:

1. 数组类型定义及使用

测试代码:

1 # 特殊ctypes类型数组类型定义
2 ArrayTestType = ctypes.c_uint8 * 10 # 重定义数据类型
3 ArrayTest = ArrayTestType(11) # 定义数据并初始化数据赋值为11
4 ArrayTest[5] = 20 # 对数据进行赋值处理
5 print('Line', sys._getframe().f_lineno, ':', ArrayTest, type(ArrayTest), ArrayTestType, type(ArrayTestType))
6 print('Line', sys._getframe().f_lineno, ':', ArrayTest[0], ArrayTest[5])

运行结果:

Line 20 : <__main__.c_ubyte_Array_10 object at 0x7fd1318e8ea0> <class '__main__.c_ubyte_Array_10'> <class '__main__.c_ubyte_Array_10'> <class '_ctypes.PyCArrayType'>
Line 21 : 11 20

这里可以看到 ArrayTestType 的类型其实为 PyCArrayType PythonC数组类型,因此 ArrayTestType 可以定义一个 unsigned char Array[10] 的数组。

注:数组类型的缩略定义方法(相当于上述步骤的两步)

# 定义一个大小为10指针实例作为缓存, 等效为 Step1:DataType = c_uint8 * LENGTH --> Step2:DataPoint = DataType()
DataPoint = (c_uint8 * LENGTH)() 

2. 动态库的加载及接口调用

测试代码:

1 # 从C语言或者C++的动态库当中加载C函数以调用
2 p = os.getcwd() + '/libfunc.so' # 获取当前的动态库的绝对路径位置
3 f = cdll.LoadLibrary(p) # 使用LoadLibrary接口加载C语言动态库
4 
5 # Python Class类 到 C struct结构体 数据类型的传输转换
6 Sfunction = f.py_struct_address # 从当前库当中取得clib中的函数py_struct_address,并重命名为Sfunction
7 Sfunction.argtypes = [POINTER(POINT), POINTER(ctypes.c_char)] # 设置当前函数的输入参数

这里使用了 os模块获取了动态库的绝对路径,并调用cdll.LoadLibrary(libpath),这里使用 argtypes 定义了动态库函数的输入参数类型,分别为结构体指针、char *指针。

3. 定义字符串类型(字符串string)

1 p = create_string_buffer(b"Hello World", 15) # create a 10 byte buffer
2 print('Line', sys._getframe().f_lineno, ':', p,sizeof(p), repr(p.raw))

创建一个string类型的缓冲空间,并返回一个字符串指针指向这串字符串,create_string_buffer 参数分别为字符串、buffer总长度,这个长度不能小于前一个参数字符串的长度大小,否则会报错,p.raw取字符串的内容。

4. Numpy数组的地址获取及应用

测试代码:

 1 # Numpy 数据类型等相互转换测试(将内存数据转换值Python当中)
 2 ImgW = 1669 # 图像宽度
 3 ImgH = 21 # 图像高度
 4 ImgC = 3 # 图像通道数
 5 ImgL = ImgW*ImgH*ImgC # 图像总长度
 6 
 7 ImgArray = np.zeros((ImgW,ImgH,ImgC), dtype=np.ubyte) # 申请图像总空间为多维 zeros 矩阵
 8 print(ImgArray.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))) # 将numpy数组转换为地址表示方式 data_as 并打印数据类型
 9 ImgArray_addr = ImgArray.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)) # 获取的指针放置在ImgArray_addr变量当中
10 print('Line', sys._getframe().f_lineno, ':', ImgArray_addr[0],ImgArray_addr[1],ImgArray_addr[2],ImgArray_addr[3])
11 
12 Imgfunction = f.py_img_address # 从当前库当中取得clib中的函数py_struct_address,并重命名为Sfunction
13 Imgfunction.argtypes = [POINTER(ctypes.c_ubyte), ctypes.c_uint32] # 设置当前函数的输入参数规划 usigned char *pointer, unsigned int arg
14 Imgfunction.restype = ctypes.c_int # 设置当前函数返回值参数为 int 类型
15 time_start = time.time()
16 Res = Imgfunction(ImgArray_addr, ImgL) # 调用Imgfunction函数
17 time_end = time.time()
18 print('Line', sys._getframe().f_lineno, ':', 'TimeCost:', (time_end - time_start)*1000, 'ms') # 记录当前函数调用消耗的时间
19 
20 print('Line', sys._getframe().f_lineno, ':\n', ImgArray[:,:,0]) # 打印0通道的数据
21 print('Line', sys._getframe().f_lineno, ':\n', ImgArray[:,:,1]) # 打印1通道的数据
22 print('Line', sys._getframe().f_lineno, ':\n', ImgArray[:,:,2]) # 答应2通道的数据

通过numpy库中数组的成员 ctypes.data_as 方法获取指定类型的指针地址,并将此地址应用在函数库的参数中。

5. 基本类型定义

测试代码:

1 # 使用byref获取ctypes类型数据的地址
2 data = ctypes.c_uint8(10) # 定义一个整数类型的变量,变量初始值为 10,相当于C语言中的 char data=42;
3 data_addr = ctypes.byref(data, 0) # 通过使用byref接口获取地址,相当于C语言中的 char *data_addr = &data; byref(obj, offset) 对应于这段 C 代码:(((char *)&obj) + offset)
4 print('Line', sys._getframe().f_lineno, ':', type(data))
5 print('Line', sys._getframe().f_lineno, ':', type(data_addr))

这里使用 ctypes.c_uint8(10) 定义一个 unsigned char 类型的数据并赋予初值为10,byref函数接口用于获取数据data的地址。

I) 完整的测试代码:

MemoryTest.py

  1 import os
  2 import sys
  3 import time
  4 import ctypes
  5 from ctypes import *
  6 from ctypes import cdll
  7 import numpy as np
  8 
  9 BUFF_SIZE = 6*1024*1024 # 基本的缓冲区域尺寸大小定义
 10 LENGTH = 2*2*3 # 数据长度定义
 11 
 12 # 类定义
 13 class POINT(Structure): # 定义了一个类,类当中的基本成员变量包括了x、y, 相当于C语言中的 struct POINT{int x;inty};
 14     _fields_ = [("x", c_int),("y", c_int),("addr", POINTER(c_uint8)),("len", c_int)]
 15 
 16 # 特殊ctypes类型数组类型定义
 17 ArrayTestType = ctypes.c_uint8 * 10 # 重定义数据类型
 18 ArrayTest = ArrayTestType(11) # 定义数据并初始化数据赋值为11
 19 ArrayTest[5] = 20 # 对数据进行赋值处理
 20 print('Line', sys._getframe().f_lineno, ':', ArrayTest, type(ArrayTest), ArrayTestType, type(ArrayTestType))
 21 print('Line', sys._getframe().f_lineno, ':', ArrayTest[0], ArrayTest[5])
 22 
 23 DataPoint = (c_uint8 * LENGTH)() # 定义一个大小为10指针实例作为缓存, 等效为 Step1:DataType = c_uint8 * LENGTH --> Step2:DataPoint = DataType()
 24 DataPoint[3] = 22
 25 
 26 point = POINT(10, 20, DataPoint,LENGTH) # 定义个类对象Obj, 相当于 struct POINT point={10,20};
 27 print('Line', sys._getframe().f_lineno, ':', point.x, point.y, point.addr[3], point.len)
 28 
 29 point = POINT(y=5) # 定义个类对象Obj, 相当于 struct POINT point={,20};
 30 print('Line', sys._getframe().f_lineno, ':', point.x, point.y)
 31 
 32 # Class类数组定义
 33 addrTest = (POINT * 1)() # 定义一个POINT结构体缓冲地址
 34 addrTest[0].x = 10 # POINT缓冲地址的第一个变量的x成员值
 35 addrTest[0].y = 11 # POINT缓冲地址的第一个变量的y成员值
 36 addrTest[0].addr = DataPoint # POINT缓冲地址的第一个变量的addr成员赋值
 37 addrTest[0].len = LENGTH # POINT缓冲地址的第一个变量的len成员赋值
 38 print('Line', sys._getframe().f_lineno, ':', addrTest, addrTest[0].x,addrTest[0].y,addrTest[0].addr[3],addrTest[0].len)
 39 
 40 TenPointsArrayType = POINT * 3 # 重定义了一个POINT数组类型,相当于C语言中的 #define TenPointsArrayType POINT*3
 41 arr = TenPointsArrayType()
 42 for pt in arr:
 43     print(pt.x, pt.y, pt.addr)
 44 
 45 # 从C语言或者C++的动态库当中加载C函数以调用
 46 p = os.getcwd() + '/libfunc.so' # 获取当前的动态库的绝对路径位置
 47 f = cdll.LoadLibrary(p) # 使用LoadLibrary接口加载C语言动态库
 48 function = f.py_point_address # 从当前库当中取得clib中的函数py_point_address,并重命名为function
 49 function.argtypes = [POINTER(c_byte)] # 设置当前函数的输入参数
 50 
 51 # Python Class类 到 C struct结构体 数据类型的传输转换
 52 Sfunction = f.py_struct_address # 从当前库当中取得clib中的函数py_struct_address,并重命名为Sfunction
 53 Sfunction.argtypes = [POINTER(POINT), POINTER(ctypes.c_char)] # 设置当前函数的输入参数
 54 
 55 p = create_string_buffer(b"Hello World", 15) # create a 10 byte buffer
 56 print('Line', sys._getframe().f_lineno, ':', p,sizeof(p), repr(p.raw))
 57 
 58 time_start = time.time()
 59 Res = Sfunction(addrTest, p)
 60 time_end = time.time()
 61 for i in range(LENGTH):
 62     print(addrTest[0].addr[i])
 63 
 64 print('Line', sys._getframe().f_lineno, ':', addrTest[0].x, addrTest[0].y, addrTest[0].len, addrTest[0].addr)
 65 print('Line', sys._getframe().f_lineno, ':', 'TimeCost:', (time_end - time_start)*1000, 'ms') # 记录当前函数调用消耗的时间
 66 
 67 # Numpy 数据类型等相互转换测试(将内存数据转换值Python当中)
 68 ImgW = 1669 # 图像宽度
 69 ImgH = 21 # 图像高度
 70 ImgC = 3 # 图像通道数
 71 ImgL = ImgW*ImgH*ImgC # 图像总长度
 72 # ImgArray = np.array([[0, 1], [2, 3]], dtype=np.uint8)
 73 ImgArray = np.zeros((ImgW,ImgH,ImgC), dtype=np.ubyte) # 申请图像总空间为多维 zeros 矩阵
 74 # ImgArray = np.array([1,2,3,4], dtype=np.int32)
 75 # print(ImgArray)
 76 # print(ImgArray.ctypes.data)
 77 print(ImgArray.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))) # 将numpy数组转换为地址表示方式 data_as 并打印数据类型
 78 ImgArray_addr = ImgArray.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)) # 获取的指针放置在ImgArray_addr变量当中
 79 print('Line', sys._getframe().f_lineno, ':', ImgArray_addr[0],ImgArray_addr[1],ImgArray_addr[2],ImgArray_addr[3])
 80 # print(ImgArray.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)).contents)
 81 # print(ImgArray.ctypes.data_as(ctypes.POINTER(ctypes.c_uint16)).contents)
 82 # print(ImgArray.ctypes.shape)
 83 # print(ImgArray.ctypes.strides)
 84 
 85 Imgfunction = f.py_img_address # 从当前库当中取得clib中的函数py_struct_address,并重命名为Sfunction
 86 Imgfunction.argtypes = [POINTER(ctypes.c_ubyte), ctypes.c_uint32] # 设置当前函数的输入参数规划 usigned char *pointer, unsigned int arg
 87 Imgfunction.restype = ctypes.c_int # 设置当前函数返回值参数为 int 类型
 88 time_start = time.time()
 89 Res = Imgfunction(ImgArray_addr, ImgL) # 调用Imgfunction函数
 90 time_end = time.time()
 91 print('Line', sys._getframe().f_lineno, ':', 'TimeCost:', (time_end - time_start)*1000, 'ms') # 记录当前函数调用消耗的时间
 92 
 93 print('Line', sys._getframe().f_lineno, ':\n', ImgArray[:,:,0]) # 打印0通道的数据
 94 print('Line', sys._getframe().f_lineno, ':\n', ImgArray[:,:,1]) # 打印1通道的数据
 95 print('Line', sys._getframe().f_lineno, ':\n', ImgArray[:,:,2]) # 答应2通道的数据
 96 
 97 # 一般类型定义以及数据取地址方法 int *pi = &i;
 98 i = ctypes.c_int(42) # 定义一个整数类型的变量,变量初始值为 42,相当于C语言中的 int i=42;
 99 pi = ctypes.pointer(i) # 通过使用pointer接口获取,相当于C语言中的 int *pi = &i;
100 print('Line', sys._getframe().f_lineno, ':', pi.contents) # 查看指针变量的信息
101 print('Line', sys._getframe().f_lineno, ':', pi[0]) # 查看指针所指向的内容,相当于C语言中的 *pi;
102 
103 # ctypes.c_byte 类型的数组定义,等效于 byte a[BUFF_SIZE];
104 a = (c_byte * BUFF_SIZE)() # 定义一个大小为BUFF_SIZE指针实例作为缓存
105 # cast(a, POINTER(c_uint8)) # 函数可以将一个指针实例强制转换为另一种 ctypes 类型
106 print('Line', sys._getframe().f_lineno, ':', a)
107 print('Line', sys._getframe().f_lineno, ':', type(a))
108 time_start = time.time()
109 function(a) # 执行function函数并传入a地址参数
110 time_end = time.time()
111 
112 for i in range(10):
113     print(a[i])
114 
115 print('Line', sys._getframe().f_lineno, ':', 'TimeCost:', (time_end - time_start)*1000, 'ms') # 记录当前函数调用消耗的时间
116 
117 # 使用byref获取ctypes类型数据的地址
118 data = ctypes.c_uint8(10) # 定义一个整数类型的变量,变量初始值为 10,相当于C语言中的 char data=42;
119 data_addr = ctypes.byref(data, 0) # 通过使用byref接口获取地址,相当于C语言中的 char *data_addr = &data; byref(obj, offset) 对应于这段 C 代码:(((char *)&obj) + offset)
120 print('Line', sys._getframe().f_lineno, ':', type(data))
121 print('Line', sys._getframe().f_lineno, ':', type(data_addr))
122 
123 # 使用id获取变量在python的地址
124 value = 'hello world'  # 定义一个字符串变量
125 address = id(value)  # 获取value的地址,赋给address
126 get_value = ctypes.cast(address, ctypes.py_object).value  # 读取地址中的变量
127 print('Line', sys._getframe().f_lineno, ':', address, get_value) # 
128 
129 # 一般Clib函数的调用
130 res = f.func(99) # 普通函数调用
131 print('Line', sys._getframe().f_lineno, ':', res)
View Code

function.c

  1 #include <stdio.h>
  2 #include <sys/shm.h>
  3 #include <string.h>
  4 #include <stdlib.h>
  5 #include <time.h>
  6 #include <sys/time.h>
  7 
  8 
  9 #define BUFF_SIZE 6*1024*1024
 10 
 11 typedef struct T_POINT{
 12     int x;
 13     int y;
 14     char * addr;
 15     int len;
 16 }POINT;
 17 
 18 time_t get_timestamp_us(void)
 19 {
 20   time_t timestamp_ms = 0;
 21   struct timeval tv;
 22   
 23   gettimeofday(&tv,NULL);
 24   timestamp_ms = tv.tv_sec * 1000 * 1000 + tv.tv_usec;
 25   return timestamp_ms;
 26 }
 27 
 28 char *file_read(unsigned long *file_bytes, char *file_name)
 29 {
 30   int file_size;
 31   FILE *fd = NULL;
 32   char *file_data = NULL;
 33   fd = fopen(file_name, "rw");
 34   if(fd < 0)
 35   {
 36     printf("File open failed...\n");
 37     return NULL;
 38   }
 39   fseek(fd, 0, SEEK_END);
 40   file_size = ftell (fd);
 41   file_data = malloc(sizeof(char)*file_size);
 42   if(file_data == NULL)
 43   {
 44     printf("Malloc failed...\n");
 45     return NULL;
 46   }
 47   fseek(fd, 0, SEEK_SET);
 48   *file_bytes = fread(file_data,sizeof(char),file_size,fd);
 49   fclose(fd);
 50   return file_data;
 51 }
 52 
 53 /* func.c */
 54 int func(int a)
 55 {
 56     return a*a;
 57 }
 58 
 59 void cycle_calc(int b)
 60 {
 61     int count = 100;
 62     while(count--){
 63         b*=2;
 64         printf("%d - %d\n", count, b);
 65     }
 66 }
 67 
 68 unsigned char * c_point_address(void)
 69 {
 70     unsigned char *Img = malloc(sizeof(unsigned char)*1000);
 71     printf("C-Address:%hhn\n", Img);
 72     memset(Img, 20, 1000);
 73     return Img;
 74 }
 75 
 76 int py_point_address(unsigned char * Addr)
 77 {
 78     unsigned char *Img = malloc(sizeof(unsigned char)*BUFF_SIZE);
 79     // printf("C-Address:%x\n", Img);
 80     // printf("Python-Address:%x\n", Addr);
 81     memset(Img, 20, BUFF_SIZE);
 82     memcpy((unsigned char * )Addr, Img, BUFF_SIZE);
 83     return 1;
 84 }
 85 
 86 int py_struct_address(POINT *pt_POINT, char *str)
 87 {
 88     int i = 0;
 89     for(i=0; i < pt_POINT->len; i++)
 90     {
 91         pt_POINT->addr[i] = i;
 92     }
 93     pt_POINT->x = 16;
 94     pt_POINT->y = 17;
 95     printf("FunctionPrint:%s\n",str);
 96     return 1;
 97 }
 98 
 99 int py_img_address(unsigned char *data, unsigned int lenght)
100 {
101     time_t st,et;
102     unsigned long count=0;
103     unsigned long i=0;
104     st = get_timestamp_us();
105     unsigned char *ImgData = file_read(&i, "./Test.PNG");
106     et = get_timestamp_us();
107     printf("C ### ReadFile time Cost:%ld\n", et - st);
108 
109     printf("Data[%ld]:%d\n", count, *(ImgData+i-1));
110 
111     st = get_timestamp_us();
112     memcpy(data, ImgData, sizeof(unsigned char)*lenght);
113     et = get_timestamp_us();
114     printf("C ### Memcpy time Cost:%ld\n", et - st);
115 
116     printf("py_img_address FunctionPrint:%ld\n", i);
117     return 1;
118 }
View Code

exe_shell.sh

1 #!/bin/bash
2 gcc -fPIC -shared function.c -o libfunc.so
3 python3 MemoryTest.py

II) 测试结果如下(测试平台: Ubuntu 18.04.6 LTS + Intel(R) Core(TM) i5-10400F CPU @ 2.90GHz ):

Line 91 : TimeCost: 0.07772445678710938 ms  102KB  Speed=1.25GB/s

二、采用共享内存方式进行IPC通信

内存共享基本方法参考 《进程间通信原理》 ,共享内存的方式需要通过其他通信方式进行进程间数据同步,从而保证共享内存在使用的过程中不被其他进程修改。

main.py

 1 from ctypes import *  
 2 import numpy as np
 3 import codecs
 4 import datetime
 5 
 6 SHM_SIZE = 1024*1024*20 # 20MBytes
 7 SHM_KEY = 123559  
 8 
 9 OUTFILE="Shared.PNG"  
10 try:  
11     rt = CDLL('librt.so')  
12 except:  
13     rt = CDLL('librt.so.1')
14 
15 shmget = rt.shmget
16 shmget.argtypes = [c_int, c_size_t, c_int]  
17 shmget.restype = c_int  
18 shmat = rt.shmat  
19 shmat.argtypes = [c_int, POINTER(c_void_p), c_int]  
20 shmat.restype = c_void_p  
21 
22 shmid = shmget(SHM_KEY, SHM_SIZE, 0o666)
23 
24 if shmid < 0:  
25     print ("System not infected")  
26 else:
27     addr = shmat(shmid, None, 0)  
28     f=open(OUTFILE, 'wb')
29     begin_time = datetime.datetime.now()
30     DataLength = int.from_bytes(string_at(addr,4), byteorder='little', signed=True)   #这里数据文件是小端int16类型
31     ImgData = string_at(addr+4,DataLength)
32     end_time = datetime.datetime.now()
33     print(DataLength, ' Bytes')
34     print('Type:',type(ImgData),' Bytes:', len(ImgData))
35     f.write(ImgData)
36     f.close()  
37 #print ("Dumped %d bytes in %s" % (SHM_SIZE, OUTFILE))
38 print("Success!",end_time-begin_time)
View Code

main.c

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <sys/shm.h>
  4 #include <string.h>
  5 #include <time.h>
  6 #include <sys/time.h>
  7 
  8 #define SHAERD_MEM_SIZE 20 * 1024 * 1024 // 20MBytes
  9 
 10 char mem_free(void *ptr);
 11 time_t get_timestamp_ms(void);
 12 char *file_read(unsigned int *file_bytes, char *file_name);
 13 
 14 int main(int argc, char *argv[])
 15 {
 16     int id = 0;
 17     size_t offset = 0;
 18     char *data = NULL;
 19     char *ImgData = NULL;
 20     unsigned int file_bytes = 0;
 21     time_t start_time, end_time;   
 22     if (argc < 2)
 23     {
 24         printf("args too less\n");
 25         return 0;
 26     }
 27     
 28     id = shmget(123559, SHAERD_MEM_SIZE, IPC_CREAT | 0777);
 29     if (id < 0)
 30     {
 31         printf("get id failed\n");
 32         return 0;
 33     }
 34     
 35     data = shmat(id, NULL, 0);
 36     if (data == NULL)
 37     {
 38         printf("shamt failed\n");
 39         return 0;
 40     }
 41 
 42     ImgData = file_read(&file_bytes, argv[1]);
 43     offset = sizeof(unsigned int);
 44     printf("Size of unsigned long:%d\n", offset);
 45     printf("Size of Image File:%d\n", file_bytes);
 46     start_time = get_timestamp_ms();
 47     memcpy(data, &file_bytes, sizeof(unsigned int));
 48     memcpy(data + offset, ImgData, file_bytes);
 49     end_time = get_timestamp_ms();
 50 
 51     printf("Time Cost:%d\n", end_time - start_time);
 52 
 53     mem_free(ImgData);
 54 
 55     return 0;
 56 }
 57 
 58 char *file_read(unsigned int *file_bytes, char *file_name)
 59 {
 60   int file_size;
 61   FILE *fd = NULL;
 62   char *file_data = NULL;
 63   fd = fopen(file_name, "rw");
 64   if(fd < 0)
 65   {
 66     printf("File open failed...\n");
 67     return NULL;
 68   }
 69   fseek(fd, 0, SEEK_END);
 70   file_size = ftell (fd);
 71   file_data = malloc(sizeof(char)*file_size);
 72   if(file_data == NULL)
 73   {
 74     printf("Malloc failed...\n");
 75     return NULL;
 76   }
 77   fseek(fd, 0, SEEK_SET);
 78   *file_bytes = fread(file_data,sizeof(char),file_size,fd);
 79   fclose(fd);
 80   return file_data;
 81 }
 82 
 83 time_t get_timestamp_ms(void)
 84 {
 85   time_t timestamp_ms = 0;
 86   struct timeval tv;
 87   
 88   gettimeofday(&tv,NULL);
 89   timestamp_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000;
 90   return timestamp_ms;
 91 }
 92 
 93 char mem_free(void *ptr)
 94 {
 95   if(NULL != ptr)
 96   {
 97     free(ptr);
 98     return 0;
 99   }
100   printf("Memory is Empty...\n");
101   return -1;
102 }
View Code

编译执行即可

gcc -o main main.c
./main sdlinux.zip # 12MB
python3 main.py

测试结果如下(测试平台:Ubuntu 18.04.6 LTS + Intel(R) Core(TM) i5-10400F CPU @ 2.90GHz ):

Success! 7.091045379638672 ms  12MB  Speed=1.67GB/s

未完待续 ~

这篇关于Python与C语言数据交互的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!