This is described in many places but i simply cannot get it to work. I am calling a C++ function from Cython:
cimport numpy as np
cdef extern from "test.h" namespace "mytest":
void test(double *A, int m)
cdef int foo():
cdef np.ndarray[double,mode="c"] a = np.array([1,2,3,4,5],dtype=float)
# pass ptr to first element of 'a'
test(&a[0], len(a))
return 0
foo()
test.cpp is just:
#include <stdio.h>
namespace mytest {
void test(double *A, int m)
{
for (int i = 0; i < m; i++)
{
printf("%d is %f\n", i, A[i]);
}
}
}
test.h just has:
namespace mytest {
void test(double *A, int m);
}
This seems to work but when is np.ascontiguousarray needed? Is it sufficient to do:
cdef np.ndarray[double,mode="c"] a = np.array([1,2,3,4,5],dtype=float)
or do you need:
cdef np.ndarray[double,mode="c"] a = np.ascontiguousarray(np.array([1,2,3,4,5],dtype=float))
second and more importantly, how can this generalize to 2d arrays?
Handling 2d arrays
Here is my attempt at passing 2d numpy arrays to C++ which does not work:
cdef np.ndarray[double,mode="c",ndim=2] a = np.array([[1,2],[3,4]],dtype=float)
which is called as:
test(&a[0,0], a.shape[0], a.shape[1])
in the cpp code:
void test(double *A, int m, int n)
{
printf("reference 0,0 element\n");
printf("%f\n", A[0][0]);
}
UPDATE: The correct answer
The correct answer is to use linear indexing for the array and not the [][] syntax. The correct way to print the 2d array is:
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
printf("%d, %d is %f\n", i, j, A[i*m + j]);
}
}
Atwice. For a 2D array you will probably have to do the index arithmetic manually. For example, if you have a C contiguous m x n array and you want to do the C equivalent of NumPy'sA[i,j]' you would have to doA[m*i+j]` instead ofA[0][0]. Dereferencing the pointer twice will probably crash Python.mis the number of rows. The datatype is taken care of when you specify the type for the pointer. I'll throw together a quick example.&s[0]syntax to pass to C).