qkhhly
qkhhly

Reputation: 1220

declaring numpy array with int type and pass array pointer to c code

I am trying to wrap some c code with cython. The place I am stuck is one function defined in a file called "algo.c":

int update_emission_mat(
// input
int* count_data, 
double *bound_state_data_pmf, double *unbound_state_data_pmf,
int silent_states_begin, int nucleosome_present, 
int nucleosome_start, int n_padding_states,
// output matrix and its dimensions
double *emission_mat, int n_obs, int n_states
) {......}

The c code is correct, as it's used and tested before. Then in "algo.h" I declared the same function:

int update_emission_mat(
// input
int *count_data, 
double *bound_state_data_pmf, double *unbound_state_data_pmf,
int silent_states_begin, int nucleosome_present, 
int nucleosome_start, int n_padding_states,
// output matrix and its dimensions
double *emission_mat, int obs_len, int n_states
);

Also, to wrap the function into cython, I have "algo.pxd" with the following in the file:

cdef extern from "algo.h":
    ...
    int update_emission_mat(
        # input
        int *count_data, 
        double *bound_state_data_pmf, double *unbound_state_data_pmf,
        int silent_states_begin, int nucleosome_present, 
        int nucleosome_start, int n_padding_states,
        # output matrix and its dimensions
        double *emission_mat, int obs_len, int n_states
    )

Then finally, in the main cython file "main.pyx", I defined a class:

cimport algo
import numpy as np
cimport numpy as np
import cython
cdef class main:
    ... 
    cdef np.ndarray data_emission_matrix
    cdef np.ndarray count_data
    ...
    # in one function of the class, I defined and initialized data_emission_matrix
    cpdef alloc_space(self):
        ...
        cdef np.ndarray[np.double_t, ndim = 2] data_emission_matrix = np.ones((self.n_obs, self.n_states), dtype = np.float64, order = 'C')
        self.data_emission_matrix = data_emission_matrix
        ...

    # in another function, I defined and initialized count_data
    cpdef read_counts_data(self, data_file):
        df = open(data_file, 'r') # data_file only contains a column of integers
        dfc = df.readlines()
        df.close()
        cdef np.ndarray[np.int_t, ndim = 1] count_data = np.array(dfc, dtype = np.int, order = 'C')    
        self.count_data = count_data

    # finally, called the c function
    cpdef update_data_emission_matrix_using_counts_data(self):
        ....

        cdef np.ndarray[np.int, ndim = 1] count_data = self.count_data
        cdef np.ndarray[np.double_t, ndim = 2] data_emission_matrix = \
            self.data_emission_matrix

        cdef int n_padding_states = 5
        algo.update_emission_mat(
            &count_data[0], &bound_state_data_pmf[0], 
            &unbound_state_data_pmf[0], self.silent_states_begin,
            self.nucleosome_present, self.nucleosome_start, 
            n_padding_states, &data_emission_matrix[0,0],
            self.n_obs, self.n_states
            )

I could not compile the file. The error message I got is complaining about taking the address of "count_data":

Error compiling Cython file:
------------------------------------------------------------
...
        self.data_emission_matrix

    cdef int n_padding_states = 5

    algo.update_emission_mat(
        &count_data[0], &bound_state_data_pmf[0],
       ^
------------------------------------------------------------

main.pyx:138:12: Cannot take address of Python variable

I am confused because I essentially treated "data_emission_matrix" the same way but cython is not complaining about that. I apologize for the tedious code. I am fairly new to cython and could not figure out the exact spot that caused the error... I appreciate any help!

Upvotes: 3

Views: 1325

Answers (1)

HYRY
HYRY

Reputation: 97261

use following code to pass the address of data buffer, if you ensure the ndarray is C_CONTIGUOUS:

<int *>count_data.data

edit:

The real problem that cause the error is the element type of count_data, it should be: np.int_t.

Upvotes: 2

Related Questions