ctypes的运用(把dataframe型数据或numpy/list数组传入c中)

以下内容仅为记录运行过程。

注:下面是C中的头文件和声明

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define DLLEXPORT __declspec(dllexport)


Python头文件部分和导入dll

from ctypes import *
import ctypes
import numpy as np
import pandas as pd

func= cdll.LoadLibrary("dll/second_dll_0406.dll")

 

1、把一个二维数组转化成一维的,传入C

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]);
        }
    }
}

Python部分:

#经测试,该种方法只适合把int类型的二维数组转化为一维数组传给C;double等浮点型不行,会在第三小节介绍如何把double等类型转化为一维数组传给C

#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)

2、把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))

 

3  、如果将python中list传入C函数数组,则需要提前转换

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部分:

# 如果将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_)

4、把dataframe型数据传给C

注:实际上是以上内容的应用

Python部分:

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)

文章来源:

ctypes的运用(把一个numpy数组传入c中)

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值