使用cython中的C函数在文件中读取和写入数组

时间:2015-04-29 17:19:06

标签: python c arrays numpy cython

我在 cython 中实例化一个类。我想通过使用给定函数计算一个float值数组的实例,并使用 c 函数将其保存在二进制文件中。对于我的类的进一步调用,如果输入文件已经存在,则通过从文件中读取数组来声明实例,否则它将再次计算它。

import numpy as np
cimport numpy as np
cimport cython

from libc.stdio cimport FILE, fopen, fwrite, fscanf, fclose, fseek, SEEK_END, ftell, stdout, stderr
cdef extern from "math.h":
    double exp(double) nogil
    double log(double) nogil

cdef class Hit(object):
    cdef public double[::1] zs, Da
    cdef char* path

    def __cinit__(self, zs=None, path=None):
        if path is None:
           raise ValueError("Could not find a path to the file which contains the table of distances")
        else:
           self.path=path
        if zs is None:
           raise ValueError("You must give an array which contains the steps!")
        self.zs=zs
        cdef Py_ssize_t i, N
        N=len(self.zs)
        cdef FILE *ptr_fr
        cdef FILE *ptr_fw
        cdef double[::1] ptr_d = np.empty((N,))
        ptr_fr = fopen(self.path, "rb")
        ptr_fw = fopen(self.path, "wb")
        if (ptr_fr==NULL):
           print "I/O Error: cannot open file {}".format( self.path)  
           for i from N > i >= 0:
               ptr_d[i]=log(self.zs[i]+1.) /(1- self.zs[i])**0.5    
           if (ptr_fw == NULL):
               print "Unable to open file!\n"
           else:
               print "Opened file successfully for writing.\n"
               fwrite(<void*>&ptr_d[0], sizeof(double), N, ptr_fw)
               fclose(ptr_fw)
               self.Da = ptr_d

        else: 
           for i from N > i >= 0:
               fscanf(ptr_fr,"%f", &ptr_d[i])

           fclose(ptr_fr)
           self.Da = ptr_d

当我第二次运行我的代码时,从读取文件返回到指针的值是正确的,但是我认为我将指针分配给内存视图的方式存在问题,因为{{1}中的所有值都是实例是零。有什么建议吗?!!

1 个答案:

答案 0 :(得分:3)

我自己的问题的答案是:

import numpy as np
cimport numpy as np
cimport cython
from libc.stdio cimport FILE, fopen, fwrite, fscanf, fclose, fprintf, fseek, ftell, SEEK_END, rewind, fread
from numpy cimport float64_t
from libc.stdlib cimport malloc, free
cdef extern from "math.h":
    double exp(double) nogil
    double log(double) nogil

cdef class Hit(object):
    cdef public double[::1] zs,  Da
    cdef char* path

    @cython.boundscheck(False)
    @cython.cdivision(True)
    @cython.wraparound(False)
    @cython.nonecheck(False)
    def __cinit__(self, path=None, zs=None):
        if path is None:
           raise ValueError("Could not find a path to the file which contains the table of distances")
        else:
           self.path=path

        if zs is None:
           raise ValueError("You must give an array which contains the steps!")
        self.zs=zs

        cdef Py_ssize_t i, N, lSize
        N=len(np.ascontiguousarray(self.zs))
        print "Input file should have ",N
        cdef FILE *ptr_fr
        cdef FILE *ptr_fw
        cdef size_t result
        cdef double *ptr_d= <double *>malloc(N * sizeof(double))
        ptr_fr = fopen(self.path, "rb")        
        if (ptr_fr==NULL):
           print "I/O Error: cannot open file {}".format( self.path) 
           for i from N > i >= 0:
               ptr_d[i]=log(self.zs[i])
               print ptr_d[i]
           ptr_fw = fopen(self.path, "wb")
           if (ptr_fw == NULL):
               print "Unable to open file!\n"

           else:

               print "Opened file successfully for writing.\n"
               fwrite(ptr_d, sizeof(double), N, ptr_fw)
               fclose(ptr_fw)
               self.Da = np.asarray(<double[:N]>ptr_d)
        else: 
           fseek (ptr_fr , 0 , SEEK_END)
           lSize = ftell (ptr_fr)
           print lSize
           rewind (ptr_fr)
           result=fread(ptr_d,sizeof(double),lSize ,ptr_fr )
           for i from N > i >= 0:
               print ptr_d[i]
           fclose(ptr_fr)
           self.Da = np.asarray(<double[:N]>ptr_d)
        print np.ascontiguousarray(self.Da)

        free(ptr_d)