我在cython中重写了python的代码,因为我是新手,我有一些问题。我的代码如下:
tools.pyx
import numpy as np
import copy
cimport numpy as np
ctypedef np.double_t DTYPE_T
cpdef double std_G,v_c
std_G=4.3e-9 # Newton's const in Mpc (km/s)^2 M_sol^{-1}
v_c = 299792.458 #km/s
cdef extern from "math.h":
double log(double) nogil
double sqrt(double) nogil
cdef extern from "gsl/gsl_math.h":
ctypedef struct gsl_function:
double (* function) (double x, void * params)
void * params
cdef extern from "gsl/gsl_integration.h":
ctypedef struct gsl_integration_workspace
gsl_integration_workspace * gsl_integration_workspace_alloc(size_t n)
void gsl_integration_workspace_free(gsl_integration_workspace * w)
int gsl_integration_qags(const gsl_function * f, double a, double b, double epsabs, double epsrel, size_t limit, gsl_integration_workspace * workspace, double *result, double *abserr)
cdef double do_callback(double x, void* params):
return (<ComovingDistMemoization>params).eval(x)
cdef class ComovingDistMemoization(object):
cdef list _memotable
def __init__(self, cosmology cosmo, memotable = None):
if memotable is None:
self._memotable = []
self._memotable = memotable
self.cosmology = cosmo
def __call__(self, double z):
if z in self._memotable:
return self._memotable[z]
def eval(z):
return 1./sqrt(self.cosmology.hubble2(z))
cdef gsl_integration_workspace* w =gsl_integration_workspace_alloc(1000)
cdef gsl_function F
F.function = &do_callback
F.params = <void*>self
cdef double result = 3, error = 5
cdef double y, err, dist
gsl_integration_qags (&F, 0, z, 0, 1e-7, 1000, w, &result, &error)
y, err = result, error
gsl_integration_workspace_free(w)
dist = self.cosmology.v_c * y #to get proper units, ie to put in the hubble length
self._memotable[z] = dist
return dist
cdef class cosmology(object):
cdef public double omega_m, omega_l, h, w, omega_r, G, v_c
cdef ComovingDistMemoization ComovingDistMemoization
def __init__(self,double omega_m = 0.3, double omega_l = 0.7, double h = 0.7, double w = -1, double omega_r = 0., double G = std_G):
self.omega_m = omega_m
self.omega_l = omega_l
self.omega_r = omega_r
self.h = h
self.w = w
self.G = G
self.v_c = v_c
self.comovingdist = ComovingDistMemoization(self)
def __copy__(self):
return cosmology(omega_m = self.omega_m, omega_l = self.omega_l, h = self.h, w = self.w, omega_r = self.omega_r, G = self.G)
property H0:
def __get__(self):
return 100*self.h #km/s/MPC
def hubble2(self, double z):
cdef double inv_a
inv_a = 1.+z
return (self.omega_r*inv_a**4 + self.omega_m*inv_a**3 + \
self.omega_l*(inv_a**(3*(1+self.w))) + (1 - self.omega_m - self.omega_l - self.omega_r)*inv_a**2)*self.H0**2
property hubble_length:
def __get__(self):
return self.v_c / self.H0
def rho_crit(self, double z):
return 3.*self.hubble2(z)/(8*np.pi*self.G)
def angulardist(self, double z, double z2 = None):
if z2 is None:
return self.comovingdist(z) / (1+z)
return (self.comovingdist(z2) - self.comovingdist(z)) / (1+z2)
class CosmologyFixedException(Exception): pass
cdef class CosmologySingleton(object):
cdef object _cosmology,startCosmology
cdef bint isMutable
cdef cosmology cosmology
def __cinit__(self, startCosmology = None, isMutable = True):
self.isMutable = isMutable
if startCosmology is None:
self._cosmology = cosmology()
else:
self._cosmology = copy.copy(startCosmology)
def get_cosmology(self):
return copy.copy(self._cosmology)
def set_cosmology(self, newcosmo):
if not self.isMutable:
raise CosmologyFixedException
self._cosmology = copy.copy(newcosmo)
cosmology = property(get_cosmology, set_cosmology)
def __getattr__(self, name):
return getattr(self._cosmology, name)
问题:
导致问题的主要部分在另一个类中声明一个类并将其作为类中的对象调用:
例如:
在ComovingDistMemoization
类里面这一行:self.cosmology = cosmology
,特别是在宇宙学类中,这个声明self.comovingdist = ComovingDistMemoization(self)
引起了一个问题,甚至最终在CosmologySingleton
类中引发了错误信息
我可以毫无错误地运行以下行:
cython tools.pyx
但是当我编译c
代码时,我收到了以下错误:
gcc -m64 -pthread -fno-strict-aliasing -Wstrict-prototypes -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/usr/include -I/vol/dalek/anaconda/include/python2.7 -c tools.c -o build/temp.linux-x86_64-2.7/tools.o
错误
tools.c: In function ‘inittools’:
tools.c:6880:3: error: ‘cosmology’ undeclared (first use in this function)
tools.c:6880:3: note: each undeclared identifier is reported only once for each function it appears in
tools.c 代码中的引用行如下:
__Pyx_XDECREF_SET(cosmology, ((struct __pyx_obj_5tools_cosmology *)__pyx_t_3));
如何在另一个类中定义和声明类,特别是作为对象?