如何将3D python数组传递给C代码然后返回? 我研究过,
我尝试过2D
test1.py
import numpy as np
import numpy.ctypeslib as npct
from numpy.ctypeslib import ndpointer
import ctypes
import sys
import time
_doublepp = ndpointer(dtype=np.uintp, ndim=2, flags='C')
_dll = ctypes.CDLL("foo_test.dll")
_foobar = _dll.foobar
_foobar.argtypes = [ctypes.c_int, ctypes.c_int, _doublepp, _doublepp]
_foobar.restype = None
def foobar(x):
y = np.zeros_like(x)
print x.__array_interface__
print x.shape[0]
print x.strides
xpp = (x.__array_interface__['data'][0]
+ np.arange(x.shape[0])*x.strides[0]).astype(np.uintp)
ypp = (y.__array_interface__['data'][0]
+ np.arange(y.shape[0])*y.strides[0]).astype(np.uintp)
print xpp
print ypp
m = ctypes.c_int(x.shape[0])
n = ctypes.c_int(x.shape[1])
o = ctypes.c_int(x.shape[2])
_foobar(m, n, o, xpp, ypp)
return y
if __name__ == '__main__':
n = sys.argv[1]
n = float(n)
dim = np.sqrt(n)
s1=time.clock()
x = np.arange(n).reshape((3,3,3))
# x = np.arange(9).reshape((3,3))
y = foobar(x)
f1 = time.clock()
print 'Execution Time is ', f1-s1, ' Second'
print y[:]
foo_test.c
#include <stdio.h>
#include <stdlib.h>
#ifdef FOO_DLL
#ifdef FOO_EXPORTS
#define FOO_API __declspec(dllexport)
#else
#define FOO_API __declspec(dllimport)
#endif //For FOO_Export
#else
#define FOO_API extern
#endif //for FOO_DLL
#ifdef __cplusplus
extern "C" {
#endif
// http://cboard.cprogramming.com/c-programming/61578-4-dimensional-array-contiguous-allocation.html#post438210
void* my_malloc(char *expr, size_t size)
{
void* result = malloc(size);
printf("Malloc (%s) is size %lu, resulting %p\n", expr, (unsigned long)size, result );
return result;
}
void my_free(void* ptr)
{
printf("Freeing : %p\n", ptr);
free(ptr);
}
#define MY_MALLOC(x) my_malloc(#x, x)
#define MY_FREE(x) my_free(x)
//Create float 2D
float **array2D(int dimx, int dimy)
{
float **allx = MY_MALLOC(dimx * sizeof *allx);
float *ally = MY_MALLOC(dimx * dimy * sizeof *ally);
float **result = allx;
int x;
for(x = 0; x < dimx ; x++, ally += dimy)
{
result[x] = ally;
}
return result;
}
//create float 3D
float ***array3D(int dimx, int dimy, int dimz)
{
float ***allx = MY_MALLOC(dimx * sizeof *allx);
float **ally = MY_MALLOC(dimx * dimy * sizeof *ally);
float *allz = MY_MALLOC(dimx * dimy * dimz * sizeof *allz);
float ***result = allx;
int x, y;
for(x = 0; x < dimx ; x++, ally += dimy)
{
result[x] = ally;
for (y = 0; y <dimy ; y++, allz += dimz)
{
result[x][y] = allz;
}
}
return result;
}
void foobar(const int m, const int n, const int o, const double*** x, double*** y)
{
float ***array3d;
// int x, y;
array3d = array3D(m,n,o);
size_t i,j,k;
for(i = 0; i< m; i++)
{
for(j = 0; j < n; j++)
{
for(k = 0; k < o; k++)
{
array3d[i][j][k] = 5.0;
y[i][j][k] = array3d[i][j][k];
}
}
}
}
#ifdef __cplusplus
}
#endif
错误说,
回溯(最近一次呼叫最后一次):文件“test1.py”,第40行,在 y = foobar(x)文件“test1.py”,第30行,在foobar中 _foobar(m,n,o,xpp,ypp)ctypes.ArgumentError:参数3 ::参数必须是ndarray
答案 0 :(得分:0)
最后,我解决了我的问题,(感谢Evert的建议)
c_multiply.c
#include "c_multiply.h"
#include <stdio.h>
void ccmultiply4d(double* array, double multiplier, int m, int n, int o, int p) {
int i, j,k, l ;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
for (k = 0; k < o; k++)
for (l = 0; l < p; l++)
{
array[i*m*n*o + j*n*o + k*o + l] = array[i*m*n*o + j*n*o + k*o + l] ;
printf("Array[%d*%d*%d*%d + %d*%d*%d + %d*%d + %d] * Multiplier = Array[%d] * %d = %.lf\n", i,m,n,o,j,n,o,k,o,l, i*m*n*o + j*n*o + k*o + l, multiplier, array[i*m*n*o + j*n*o + k*o + l]);
}
}
test.pyx
import cython
# import both numpy and the Cython declarations for numpy
import numpy as np
cimport numpy as np
# declare the interface to the C code
cdef extern from "c_multiply.h":
void ccmultiply4d(double* array, double value, int m, int n, int o, int p)
@cython.boundscheck(False)
@cython.wraparound(False)
def multiply(np.ndarray[double, ndim=4, mode="c"] input not None, double value):
"""
multiply (arr, value)
Takes a numpy arry as input, and multiplies each elemetn by value, in place
param: array -- a 2-d numpy array of np.float64
param: value -- a number that will be multiplied by each element in the array
"""
cdef int m, n, o, p
m, n, o, p = input.shape[0], input.shape[1], input.shape[2], input.shape[3]
ccmultiply4d(&input[0,0,0,0], value, m, n, o, p)