0

How to pass 3D python array to C code then get return back? I have researched,

I have tried for 2D

Source : - 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 

The Error said,

Traceback (most recent call last): File "test1.py", line 40, in y = foobar(x) File "test1.py", line 30, in foobar _foobar(m, n, o, xpp, ypp) ctypes.ArgumentError: argument 3: : argument must be an ndarray

9
  • Have you considered using Cython to interface with your numpy array with the C code. See for example this question. Commented Oct 22, 2016 at 10:53
  • I have read it, yesterday. It is just for 2D array. i don't know to using it to pass 3D array, Evert.I'm newbie in Python Programming. Btw, thanks for your reply. Commented Oct 22, 2016 at 11:43
  • It really can't be that complicated to go from cdef np.ndarray[double,mode="c",ndim=2] array2d and &array2d[0,0], to using np.ndarray[double,mode="c",ndim=3] array3d and passing &array3d[0,0,0]. Commented Oct 22, 2016 at 11:57
  • Also have a look at numpy pointer to C on the cython Github wiki. Commented Oct 22, 2016 at 12:01
  • Okay, I will try that. I'll post my result later. Commented Oct 22, 2016 at 13:12

1 Answer 1

-1

Finally, I solved my problem, (Thanks to Evert for suggestion)

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)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.