2017-06-13 9 views
0

私はcythonの初心者です。現在、拡張型について学習しようとしていますが、次の例(説明の下にあるコード)でポインタの値がどうなるか理解できません。拡張型の属性としてのポインタcython

練習として、私はダミーソルバーを実装しています。問題は2つの数字「a」と「b」で表され、解は「s」(s = a * b)によって表されます。

私は2つの対応するCの構造、problemsolutionを定義しました。問題の構造体には、2つのintメンバー 'a'と 'b'があります。解構造には1つのメンバー 'があります。問題の構造体を初期化する関数は、init_problem(problem *p,int a, int b)です。また、構造体へのポインタをとり、解を返す関数が1つあります(solution solve(problem *p))。最後に、他の2つの関数が値(void dump_problem(problem *p)void dump_solution(solution *s))を出力します。これらのすべてはcdef宣言を使用しています。属性およびその他の属性として構造体へのポインタを用いたもの(Solver_sSolver_pとして構造体を使用して、C関数をラップdef機能do_things(int a,int b)、二つcdef class、いずれか

次に私は、PythonにCコードを公開する3つの方法を使用しましたそれぞれ問題と解決策を印刷するためのラッピング方法を含む)。 Solver_sクラスは期待通りに動作します。ただし、Solver_pを使用すると、ポインタが初期化されていないように見え、不正な値が返されます(test_pointersと出力セクションを参照)。

私はポインタとその範囲についての細かい点を逃し推測するが、私は何が起こっているか理解できません。これを得るための助けがあれば幸いです。私はOS X 10.11.6(エルキャピタン)でpython 3.5.3とcython 0.25.2を使用しています

P .:最初に尋ねているので、明確ではない場合は明確にしておきます!

pointers.pyx

from libc.stdio cimport printf 

cdef struct problem: 
    int a 
    int b 

cdef struct solution: 
    int s 

cdef void init_problem(problem *p,int a, int b): 
    p.a = a 
    p.b = b 

cdef solution solve(problem *p): 
    cdef solution s 
    s.s = p.a * p.b 
    return(s) 

cdef void dump_problem(problem *p): 
    printf("Problem dump: a = %d,b = %d\n",p.a,p.b) 

cdef void dump_solution(solution *s): 
    printf("Solution dump: s= %d\n",s.s) 

def do_things(int a,int b): 
    cdef problem p 
    init_problem(&p,a,b) 
    cdef solution s = solve(&p) 
    dump_problem(&p) 
    dump_solution(&s) 

cdef class Solver_s: #Structs as attributes of Solver 
    cdef problem p 
    cdef solution s 
    def __cinit__(self,int a,int b): 
     print("\tInside Solver_s __cinit__") 
     init_problem(&self.p,a,b) 
     dump_problem(&self.p) 
     self.s = solve(&self.p) 
     dump_solution(&self.s) 
     print("\tGetting out of Solver_s __cinit__") 

    def show_problem(self): 
     dump_problem(&self.p) 

    def show_solution(self): 
     dump_solution(&self.s) 

cdef class Solver_p: #Pointers to structs as attributes 
    cdef problem *pptr 
    cdef solution *sptr 

    def __cinit__(self,int a, int b): 
     print("\tInside Solver_p __cinit__") 
     cdef problem p 
     self.pptr = &p 
     cdef solution s 
     self.sptr = &s 
     init_problem(self.pptr,a,b) 
     dump_problem(self.pptr) #It shows right values 
     self.sptr[0] = solve(self.pptr) 
     dump_solution(self.sptr) #It shows right values 
     print("\tGetting out of Solver_p __cinit__") 


    def show_problem(self): 
     dump_problem(self.pptr) 

    def show_solution(self): 
     dump_solution(self.sptr) 

test_pointers.py

import pyximport; pyximport.install() 
import pointers 

print("\tSolving as a function") 
pointers.do_things(2,3) 

print("\tSolving as a Extended Type, structs as attributes") 
sol_s = pointers.Solver_s(4,5) 
print("\t###Problem definition unsing Solver_s methods###") 
sol_s.show_problem() 
print("\t###Solution definition using Solver_s methods###") 
sol_s.show_solution() 


print("\tSolving as a Extended Type, pointers to structs as attributes") 
sol_p = pointers.Solver_p(6,7) 
print("\t###Problem definition unsing Solver_p methods###") 
print("\t###Gives weird values###") 
sol_p.show_problem() 
print("\t###Solution definition using Solver_p methods###") 
print("\t###Gives weird values###") 
sol_p.show_solution() 

出力

Solving as a function 
Problem dump: a = 2,b = 3 
Solution dump: s= 6 
    Solving as a Extended Type, structs as attributes 
    Inside Solver_s __cinit__ 
Problem dump: a = 4,b = 5 
Solution dump: s= 20 
    Getting out of Solver_s __cinit__ 
    ###Problem definition unsing Solver_s methods### 
Problem dump: a = 4,b = 5 
    ###Solution definition using Solver_s methods### 
Solution dump: s= 20 
    Solving as a Extended Type, pointers to structs as attributes 
    Inside Solver_p __cinit__ 
Problem dump: a = 6,b = 7 
Solution dump: s= 42 
    Getting out of Solver_p __cinit__ 
    ###Problem definition unsing Solver_p methods### 
    ###Gives weird values### 
Problem dump: a = 1,b = 0 
    ###Solution definition using Solver_p methods### 
    ###Gives weird values### 
Solution dump: s= 185295816 

答えて

2
Solver_p.__cinit__

psのみコールの持続時間のために存在するローカル変数であります__cinit__になります。 Solver_pインスタンスは呼び出しを超えて持続するため、ポインタの寿命はほとんどの場合無効なデータになります。あなたが割り当てるすべてのメモリが適切に解放されることを確認するために注意する必要があり

# at the top 
from libc.stdlib cimport malloc, free 

cdef class Solver_p: 
    # .... 
    def __cinit__(self,...): 
     self.pptr = <problem*>malloc(sizeof(problem)) 
     self.sptr = <solution*>malloc(sizeof(solution)) 
     # ... 
    def __dealloc__(self): 
     free(self.pptr) 
     free(self.sptr) 
     # ... 

解決策ではなく、ヒープメモリを割り当てることです。


私のアドバイスは、あなたが正しくCでのポインタの使用方法を理解していないならば、あなたはCythonでそれらを使用する必要がありませんということです。

関連する問題