linux c s传递数据类型,通过ctypes向C程序传递一维和二维数组(Linux环境下)

使用ctypes可以在python中调用C程序,它提供与C相兼容的数据类型,比如整数类型,浮点数类型,数组等等。这篇文章主要在Linux环境下进行,作为自己日常学习的笔记,如有不对的地方欢迎拍砖。

我们先从最简单的一维数组的例子开始,比如我们有个C函数addOne它的作用是使输入的数组的每个元素+1, 我们想用python程序调用它,从python中向该c函数输入参数,在c程序中将每个值+1之后将数组返还给python程序,该联合的程序主要有两个部分构成:C语言部分和python部分,依次进行说明。

C程序部分的编写和生成链接库

1 //addOne.c2 //这个程序将输入数组的每个元素值+13 //输入参数:数组a,及a的元素个数n

4 void addOne(unsigned char *a,intn)5 {6 for(int i=0;i

我们写好了这个程序之后,我们需要让他成为动态链接库 addOne.so

$ gcc addOne.c -fPIC -shared -o libAddOne.so

其中几个参数的含义是:

-fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的(参考自http://blog.sina.com.cn/s/blog_54f82cc201011op1.html)

-shared 该选项指定生成动态链接库

-o 指定输出目标名称

在python脚本中调用该库

1 #addOneMain.py2 import ctypes

3 arr=(ctypes.c_uint8*3)(0,1,2)4

5 adder=ctypes.CDLL('./libAddOne.so')6 adder.addOne(arr,3)7

8 for i inrange(0,len(arr)):9 print(arr[i],end=' ')10 print()

该程序首先定义了一个与C相兼容的数组arr,该数组的创建方法是将一个ctypes的基本数据类型乘以一个正整数。之后使用CDLL实例化了一个对象adder,该adder对象中有addOne这个方法。之后将arr这个数组传递给C函数,再将处理结果打印出来。运行上面的python程序可以得到结果为:

1 2 3

由上面的小例子可以引出一下的一些基本知识。

ctypes 常用数据类型

我平时在写程序的时候,经常用到的几个ctypes数据类型分别有:基本数据类型,数组,指针。

基本数据类型

ctypes 中的常用基本数据类型如下表,完整的表格可以参考https://docs.python.org/3.6/library/ctypes.html

ctypes 类型

C 类型

python 类型

c_int8

char

int

c_uint8

unsigned char

int

c_float

float

float

c_bool

_Bool (C99 标准)

bool(1)

数组

ctypes 官方所推荐的构成一维数组的方法是将ctypes中的基本类型乘以一个正整数,比如上述例子中构造一个c_uint8型数组arr,其中包含3个元素,分别是"0,1,2",我们就可以这样构造它

arr=(ctypes.c_uint8*3)(0,1,2)

当然,我们也可以不明确初始化其值,ctypes会默认将所有元素的值设置为0

arr=(ctypes.c_uint8*3)()

这样数组中每个元素的值都是0。在学会使用ctypes声明一维数组之后,我们来讨论一下如何声明二维数组,上个例子中的一维数组,每个元素是一个uint8类型的值,那么二维数组是什么呢,二维数组相当于一个数组的外面又套着一个数组,我们可以通过下面的代码来体会一下。

brr=((ctypes.c_int*2)*3)((ctypes.c_int*2)(1,2),(ctypes.c_int*2)(3,4),(ctypes.c_int*2)(5,6))

通过这样的声明,我们就能得到一个3*2的数组,该数组相当于有一个1*3的数组brr,它的每个元素都是一个1*2的uint8型的数组。当然,我们也可以不先对它赋值,这样ctypes就会自动为每个值赋值为0,即

brr=((ctypes.c_int*2)*3)()

接下来,我们通过一个例子来验证一下,我们在python中声明这个数组brr,然后将它传递给C程序,

1 #initArrayMain.py

2 importctypes3

4 brr=((ctypes.c_int*2)*3)()5 init=ctypes.CDLL('./libInitArray.so')6 init.initArr(brr)7 for i in range(0,6):8 print(brr[int(i/2)][i%2],end=' ')9 if i%2:10 print()

在C程序中将0-5依次赋值给这6个元素

1 //initArray.c

2 void initArr(int arr[][2]){3 for(int i=0;i<6;i++)4 {5 arr[i/2][i%2]=i;6 }7 }

最后运行结果:

0 1

2 3

4 5

指针

将一个ctypes的基本类型的变量通过ctypes.pointer()函数就可以声明一个指向该变量的指针啦

i=ctypes.c_int(8)

pi=ctypes.pointer(i)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值