在Cython中使用typedef结构体
我在头文件 dcm.h 中有以下定义:
typedef struct
{
double alpha;
double gamma;
double tau;
} ThetaDCM;
我想在 cython 中引入它,所以我写了:
cdef extern from "dcm.h":
ctypedef struct ThetaDCM:
np.float64_t alpha
np.float64_t gamma
np.float64_t tau
现在我想给一个 ThetaDCM 的数组分配内存。我有以下代码:
cdef ThetaDCM *c_theta = <ThetaDCM *> malloc(nt * nb * sizeof(ThetaDCM))
free(c_theta)
但是这段代码没有编译通过,并且报了以下错误:
error: ‘ThetaDCM’ undeclared (first use in this function)
__pyx_v_c_theta = ((ThetaDCM *)malloc(((__pyx_v_nt * __pyx_v_nb) * (sizeof(ThetaDCM)))));
还有其他与这个错误相关的问题。如果我在 extern 块外定义 ThetaDCM,代码就能正常编译。因此,如果我引入 Theta,cython 就无法识别我的声明。有没有什么标准的方法来解决这个问题?
编辑:
我的文件头比我发布的内容要复杂一些。它是:
# 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
顶部的指令是用来检查编译器是否是 nvcc,这是一个用于 cuda 代码的编译器。现在我意识到有一个错误,我应该写成:
# 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
让我困惑的是,尽管有 #ifdef CUDACC,但 cython 代码还是编译通过了。我使用 cython 来包装在第一个 #ifdef 语句内定义的 c 函数(比如 llh_m0t),所以让我感到困惑的是,cython 能看到那些函数的定义。
2 个回答
1
可能是因为你用的 cython 版本太旧(或者是个太... 测试版?)导致的问题。
我同意这不算真正的答案——更像是一个很长的评论……不过我用 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
1
Cython不支持像你在头文件中需要的那样使用#define
宏来进行条件编译。
dcm.h
# ifdef __CUDACC__ typedef struct { double alpha; double gamma; double tau; } ThetaDCM; # endif
这里有一个简单的解决办法:
dcm.pyh
#define __CUDACC__ #include "dcm.h"
dcm.pyx
[...] cdef extern from "dcm.pyh": # ^^^ [...]