以下内容仅为记录运行过程。
注:下面是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)
文章来源: