python - 将3d数组传递给C代码

时间:2016-10-22 09:18:43

标签: python c numpy ctypes

如何将3D python数组传递给C代码然后返回? 我研究过,

我尝试过2D

资料来源:   - http://cboard.cprogramming.com/c-programming/61578-4-dimensional-array-contiguous-allocation.html#post438210

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

1 个答案:

答案 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)