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

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部