python调用c++ ctype list传数组
关于ctype与python list的转换很简单,大家记住下面两条就够用了,后面是练习
list传进C数组
import numpy as np
from ctypes import *
mylist = [101, -101, ..., 101, -101]##your list
mycbytearray = (c_byte * len(mylist))(*mylist)
C数组传进list
my_nparray = np.frombuffer(my_cbyte_array, dtype=np.uint8)
list=my_nparray.tolist()
ctypes 结构体
struct test
{
int amt_barley;
int amt_water;
};
class test(Structure):
_fields_ = [
("a", c_int),
("b", c_int),
]
typedef struct StructPointerTest
{
char name[20];
int age;
}StructPointerTest, *StructPointer;
StructPointer testfunction() // 返回结构体指针
{
StructPointer p = (StructPointer)malloc(sizeof(StructPointerTest));
strcpy(p->name, "Joe");
p->age = 20;
return p;
}
结构体传到python:
lib.testfunction.restype = POINTER(StructPointer) #指定函数返回值的数据结构
p = lib.testfunction()
#!/bin/env python
# coding=UTF-8
from ctypes import *
#python中结构体定义
class StructPointer(Structure):
_fields_ = [("name", c_char * 20), ("age", c_int)]
if __name__ == "__main__":
lib = cdll.LoadLibrary("./libmylib.so")
lib.testfunction.restype = POINTER(StructPointer) #指定函数返回值的数据结构
p = lib.testfunction()
print "%s: %d" %(p.contents.name, p.contents.age)
python的ctype结构体传入c结构体
SPTobj = pointer(StructPointerTest(1, 2))
so_obj = cdll.LoadLibrary(“./libstruct.so”)
so_obj.test(SPTobj)
#include
typedef struct StructPointerTest* StructPointer;
struct StructPointerTest{
int x;
int y;
};
void test(StructPointer p) {
p->x = 101;
p->y = 201;
}
from ctypes import *
class StructPointerTest(Structure):
#`_fields`属性(字段)
_fields_ =[('x', c_int),
('y', c_int)]
Usage:
##Structure Pointer Operation
SPTobj = pointer(StructPointerTest(1, 2))
print SPTobj
print SPTobj.contents.x
print SPTobj.contents.y
so_obj = cdll.LoadLibrary("./libstruct.so")
so_obj.test(SPTobj)
ctype普通类型值的进出
#进
ct_int = ctypes.c_int(100)
#出
ct_int.value
buf = create_string_buffer(b'12345')#进
buf.value#出
ct_int = ct_int(123)#进
ip = pointer(ct_int)#进 普通对象变成指针对象
a=ip.contents#出
a.value#出
#cast 强制指针类型转换
ct_int_array = c_int * 10(*([x for x in range(10)])#进
数字类型的数组是一个可迭代对象,其可通过for循环、next方法等方式进行迭代,
以获取其中的每一个值。例:
for i in (c_double * 10)(1, 2, 3): #出
print(i)
ctypes.memmove(dst, src, count)
ctypes.memset(dst, c, count)
#只有cast通过POINTER转换才能做到
length = 100
#某个Structure pointer object,转为Array pointer object.
p = cast(pointer(s), POINTER(c_char * length))#进
#得到Structure的原始数据
raw = p.contents.raw
s1 = cast(pointer(arr),POINTER(Structure))#出
#又把bytes 恢复成了ctype的structure
s1.contents
#获得数据的内存存储地址
a = c_int(100)
addressof(a)
hex(addressof(a))
byref(a)
列表推导式
基本使用
创建一个0-10的列表
a_range = range(10)
# 对a_range执行for表达式
a_list = [x * x for x in a_range]
# a_list集合包含10个元素
print(a_list)
a = [x for x in range(11)]
print(a)
在循环的过程中使用if
创建一个1-10之间偶数的列表
a = [x for x in range(11) if x%2==0]
2个for循环
a = [(x,y) for x in range(3) for y in range(3)]
print(a)
输出结果:
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
字典推导式
arry = [('a',3),('b',4),('c',5)]
dict_ = {key:value for (key,value) in arry}
print(dict)
将字符串以竖线拆分,变成字典k:1的形式
str1 = 'k:1|k1:2|k2:3|k3:4'
def dict_func(str1):
dict1 = {}
for item in str1.split('|'):
key,value = item.split(':')
dict1[key] = value
return dict1
print(dict_func(str1))
#结果
{'k': '1', 'k1': '2', 'k2': '3', 'k3': '4'}
- 列表推倒式: [结果 for 变量 in 可迭代对象 if 条件筛选]
multiples = [i for i in range(30) if i % 3 is 0]
print(multiples)
def squared(x):
return x*x
multiples = [squared(i) for i in range(30) if i % 3 is 0]
print( multiples)
- 生成器表达式: (结果 for 变量 in 可迭代对象 if条件筛选), 没有元组推倒式
将俩表推导式的[]改成()即可得到生成器。
multiples = (i for i in range(30) if i % 3 is 0)
print(type(multiples))
- 字典推倒式: {结果(k:v) for 变量 in 可迭代对象 if 条件筛选}
mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
mcase_frequency = {
k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0)
for k in mcase.keys()
if k.lower() in ['a','b']
}
print (mcase_frequency)
mcase = {'a': 10, 'b': 34}
mcase_frequency = {v: k for k, v in mcase.items()}
print (mcase_frequency)
- 集合推倒式: {结果(k)for 变量 in 可迭代对象 if 条件筛选} 自带去重功能
squared = {x**2 for x in [1, 1, 2]}
print(squared)
list2 = [x*10 if x%2 == 0 else x*100 for x in range(0,21) ]
print(list2)
print(type(list2))
三元条件运算符
num = inpu("请输入一个数字")
print(num if int(num)<10 else "数字太大")
range 对象
range 对象是一个迭代器对象
range(start, end [,step])
生成的数值序列从 start 开始到 end 结束(不包含 end)。若没有填写 start,则默认从 0 开始。step 是可选的步长,默认为 1
names = ("高淇","高老二","高老三","高老四")
ages = (18,16,20,25)
jobs = ("老师","程序员","公务员")
for name,age,job in zip(names,ages,jobs):
print("{0}--{1}--{2}".format(name,age,job))
print([x for x in range(1,5)])
print([a for a in "abcdefg"])
print([x*2 for x in range(1,20) if x%5==0 ])
[10, 20, 30]
#用两层for循环
print([(row,col) for row in range(1,10) for col in range(1,10)])
python调用c++ ctype list传数组或者返回数组的方法
把numpy的二维数组打包成ctypes的标准数组形式,传送给C
C部分
:
//使用double ptr[][3]可行,而使用double **ptr不可用
DLLEXPORT double szSecTest_double(double ptr[][3], int m,int n){
if(ptr){
int i = 0,j=0;
printf("\n");
for (i = 0; i < m; ++i)
for(j = 0; j < n; ++j)
printf("%f | ", ptr[i][j]);
printf("\n");
}
return ptr[0][0];
}
Python部分:
#把numpy的二维数组打包成ctypes的标准数组形式,传送给C。但存在在C中定义需要规定列数的限制,不能为如:double **a的形式
def Convert1DToCArray(TYPE, ary):
arow = TYPE(*ary.tolist())
return arow
def Convert2DToCArray(ary):
ROW = c_double * len(ary[0])
rows = []
for i in range(len(ary)):
rows.append(Convert1DToCArray(ROW, ary[i]))
MATRIX = ROW * len(ary)
return MATRIX(*rows)
a = np.array([[1.0, 2.0, 2.0], [1.0, 3.0, 4.0]])
caa = Convert2DToCArray(a)
print(caa,type(a))#<__main__.c_double_Array_3_Array_2 object at 0x0A6D88A0> <class 'numpy.ndarray'>
func.szSecTest_double.restype = c_double#一定要注意这里把返回类型定义为c_double,否则值有误
print(func.szSecTest_double(caa, 2,3))
python中list传入C函数数组,则需要提前转换
DLLEXPORT void show_matrix(double *matrix, int rows, int columns)
{
int i, j;
for (i=0; i<rows; i++) {
for (j=0; j<columns; j++)
printf("matrix[%d][%d] = %.3lf ", i, j, matrix[i*columns+ j]);
printf("\n");
}
}
# 如果将python中list传入C函数数组,则需要提前转换
a_list = [1.0, 2.0, 3.0, 4.0, 5.0,6.0]
a_arr= (ctypes.c_double * len(a_list))(*a_list) #有点类似malloc的方式生成a_arr
func.show_matrix(a_arr, 2, 3)
def Convert2DTo1D_numpy(arrTwo):
rows, cols = arrTwo.shape
arr=[]
for i in range(rows):
for j in range(cols):
arr.append(arrTwo[i][j])
#print(arrTwo[i][j])
return arr
#先把二维numpy数组转化为一维list数组,再转化为可传入C函数的数组
arrTwo = np.array([[1.0, 2.0, 3.0, 4.0],[5.0,6.0,7.0,8.0]])
row_, col_ = arrTwo.shape
arrTwo_list=Convert2DTo1D_numpy(arrTwo)
print(arrTwo_list)
arrTwo= (ctypes.c_double * len(arrTwo_list))(*arrTwo_list)
func.show_matrix(arrTwo, row_, col_)
把dataframe型数据传给C
def data_tranfer(dataFra):
# dataframe转化为numpy
dataFra = dataFra.values
# numpy二维转一维list
dataFra = Convert2DTo1D_numpy(dataFra)
#list转化为可以传递给C的形式
data = (ctypes.c_double * len(dataFra))(*dataFra)
return data
def label_tranfer(labelFra):
# dataframe的某一列转化为list,eg:‘label’列
labelFra = labelFra['label'].tolist()
# list转化为可以传递给C的形式
data = (ctypes.c_double * len(labelFra))(*labelFra)
return data
data=pd.read_csv('iris.txt',header=None)
data.columns=['sepal_length','sepal_width','petal_length','petal_width','label']
data['label']=data.label.apply(lambda x: 1 if x=='Iris-setosa' else -1)
label=data[['label']]
data.drop(['label'],axis=1,inplace=True)
rows=data.shape[0]
cols=data.shape[1]
trainData =data_tranfer(data)
trainLabel = label_tranfer(label)
func.show_matrix(trainData, rows, cols)
把一个二维数组转化成一维的,传入C
DLLEXPORT void show_matrix_int(int *matrix, int rows, int columns)
{
int i, j;
for (i=0; i<rows; i++) {
for (j=0; j<columns; j++) {
printf("matrix[%d][%d] = %d\n", i, j, matrix[i*rows + j]);
}
}
}
#arr = np.zeros((3,5))
arr = np.array([[1,2,3,4],[5,6,7,8]])
#tmp = np.asarray(arr)#可以省略这一步,前后无区别
#print(type(arr),type(tmp))
rows, cols = arr.shape
dataptr = arr.ctypes.data_as(ctypes.c_char_p)
print(type(dataptr))#<class 'ctypes.c_char_p'>
func.show_matrix_int(dataptr, rows, cols)
libusb使用
def aoa_update_point(self, action, x, y, ops=0):
global report
if ops == 0:
# left = up =0
x, y = self.axis_convert(x, y)
real_x = x - self.ref_x
real_y = y - self.ref_y
else:
real_x = x
real_y = y
# LOGGER.info('real point(%d %d)',real_x,real_y)
if action == 'move' or action == 'down':
report = Report(REPORT_ID, 1, 0, 0, 0, int(real_x), int(real_y))
if action == 'up':
report = Report(REPORT_ID, 0, 0, 0, 0, int(real_x), int(real_y))
if ops == 0:
self.set_ref(x, y)
#transfer是1个Structurue pointer obj
transfer = U.libusb_alloc_transfer(0)
# contents是实体
transfer.contents.actual_length = sizeof(Report)
# p_report = cast(pointer(report), c_void_p)
transfer.contents.buffer = cast(pointer(report), c_void_p)
# put report buffer into control_buffer
control_buffer = create_string_buffer(sizeof(Report) + LIBUSB_CONTROL_SETUP_SIZE)
# python级别的内存填充,memmove + addressof
memmove(addressof(control_buffer) +
LIBUSB_CONTROL_SETUP_SIZE, addressof(report),
sizeof(report))
# 可以看出这个是signed char 0x1 ---> 0x1 0x0 小端!
# 实际调用了:
# setup = cast(addressof(control_buffer), libusb_control_setup_p).contents
U.libusb_fill_control_setup(
addressof(control_buffer),
U.LIBUSB_ENDPOINT_OUT | U.LIBUSB_REQUEST_TYPE_VENDOR,
AndroidA0AProtocl.AOA_SEND_HID_EVENT.value[0],
1,
0,
6)
# LOGGER.info(control_buffer.raw)
U.libusb_fill_control_transfer(
transfer,
self.aoa_handle,
pointer(control_buffer),
null_callback,
None,
0)
transfer.contents.flags = U.LIBUSB_TRANSFER_FREE_BUFFER | U.LIBUSB_TRANSFER_FREE_TRANSFER
rets: int = U.libusb_submit_transfer(transfer)
if rets < 0:
LOGGER.info(U.libusb_error_name(rets))
return rets
return rets
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » python调用c++ ctype list传数组与for if 列表推导式
发表评论 取消回复