Reputation: 439
I have the following definition in the header file dcm.h:
typedef struct
{
double alpha;
double gamma;
double tau;
} ThetaDCM;
I want to import it in cython, so I have:
cdef extern from "dcm.h":
ctypedef struct ThetaDCM:
np.float64_t alpha
np.float64_t gamma
np.float64_t tau
Now I want to allocate memory to an array of ThetaDCM's. I have the following:
cdef ThetaDCM *c_theta = <ThetaDCM *> malloc(nt * nb * sizeof(ThetaDCM))
free(c_theta)
This did not compile and reported the following error:
error: ‘ThetaDCM’ undeclared (first use in this function)
__pyx_v_c_theta = ((ThetaDCM *)malloc(((__pyx_v_nt * __pyx_v_nb) * (sizeof(ThetaDCM)))));
There where other errors related to this one. If I define ThetaDCM outside the extern block, the code compiles without problem. Therefore, if I import Theta, cython cannot see my declaration. Is there any standard way to solve this?
Edit:
The header of my file was a bit more complicated than what I posted. It was
# ifdef __CUDACC__
# ifndef DDM_HEADER
# define DDM_HEADER
#include "math.h"
#include "curand_kernel.h"
#include "curand.h"
#include <stdio.h>
...
# endif
# ifdef __CUDACC__
# define BDDM_EXTERN extern "C"
# else
# define BDDM_DEVICE
# endif
BDDM_EXTERN
int llh_m0t( double *x, double *y, double *u,
double *theta, double *ptheta, int ny, int nt, double *llh);
...
typedef struct
{
double alpha;
double gamma;
double tau;
} ThetaDCM;
# endif
The directive on top is used to check if the compiler is nvcc, a compiler for cuda code. Now I realize that there was an error and that I should have had:
# ifndef DDM_HEADER
# define DDM_HEADER
# ifdef __CUDACC__
#include "math.h"
#include "curand_kernel.h"
#include "curand.h"
#include <stdio.h>
...
# endif
BDDM_EXTERN
int llh_m0t( double *x, double *y, double *u,
double *theta, double *ptheta, int ny, int nt, double *llh);
...
typedef struct
{
double alpha;
double gamma;
double tau;
} ThetaDCM;
# endif
What confused me is that the cython code compiled despite of the # ifdef CUDACC. I used cython to wrap c functions defined inside the first #ifdef statement (like llh_m0t), so the confusing thing is that cython could see those function definitions.
Upvotes: 2
Views: 4985
Reputation: 51990
Cython does not provide support to #define
macro for conditional compilation as required by your header:
dcm.h
# ifdef __CUDACC__ typedef struct { double alpha; double gamma; double tau; } ThetaDCM; # endif
A quick workaround:
dcm.pyh
#define __CUDACC__ #include "dcm.h"
dcm.pyx
[...] cdef extern from "dcm.pyh": # ^^^ [...]
Upvotes: 1
Reputation: 51990
Probably an issue with an old (or too ... beta ?) version of cython.
I agree this is not really an answer -- mostly a very long comment... but this works for me using cython 0.20.0:
dcm.h
typedef struct { double alpha; double gamma; double tau; } ThetaDCM;
dcm.pyx
cimport numpy as np from libc.stdlib cimport malloc, free nt = 1 nb = 1 cdef extern from "dcm.h": ctypedef struct ThetaDCM: np.float64_t alpha np.float64_t gamma np.float64_t tau cdef ThetaDCM *c_theta = <ThetaDCM *> malloc(nt * nb * sizeof(ThetaDCM)) print(hex(<long>c_theta)) free(c_theta)
sh$ cython dcm.pyx
sh$ gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I../include/python3.4m/ -L../lib/python3.4/ dcm.c -o dcm.so
sh$ python3Python 3.4.1 (default, Aug 20 2014, 14:47:11)
[GCC 4.7.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import dcm
0x23e44f0
Upvotes: 2